ThreadStatic属性如何工作?
[ThreadStatic]
属性如何工作? 我假定编译器会发出一些IL来填充/检索TLS中的值,但是看起来反汇编似乎并不是在这个层次上做的。
作为一个后续,如果你把它放在非静态成员上会发生什么? 我们有一个开发者犯了这个错误,编译器甚至没有提出警告。
更新
第二个问题在这里回答: ThreadStatic用静态C#
在.NET JIT编译器中,线程静态的实现语义低于IL级别。 像VB.NET和C#一样发布到IL的编译器不需要知道任何有关Win32 TLS的内容,就可以读取和编写具有ThreadStatic属性的variables的IL代码。 只要C#知道这个variables没有什么特别之处 – 它只是一个读写东西的位置。 它有一个属性的事实对C#没有任何影响。 C#只需要知道为该符号名称发出IL读或写指令。
核心CLR是负责使IL在特定硬件架构上工作的“重负”。
这也解释了为什么把这个属性放在一个不合适的(非静态的)符号上没有得到编译器的反应。 编译器不知道该属性需要什么特殊的语义。 像FX / Cop这样的代码分析工具应该知道这一点。
另一种查看方式:CIL定义了一组存储范围:静态(全局)存储,成员存储和堆栈存储。 TLS不在该列表中,很可能是因为TLS不需要在该列表中。 如果IL读取和写入指令足以在TLS属性标记符号时访问TLS,为什么IL对TLS有特殊的表示或处理? 这不是必需的。
[ThreadStatic]属性如何工作?
你可以认为用ThreadStatic标记的字段被附加到一个线程中,并且它的生命周期与线程的生命周期相当。
所以在伪代码中ThreadStatic
类似于(通过语义)有一个键值附加到一个线程:
Thread.Current["MyClass.myVariable"] = 1; Thread.Current["MyClass.myvariable"] += 1;
但语法只是更容易:
class MyClass { [ThreadStatic] static int myVariable; } // .. then MyClass.myVariable = 1; MyClass.myVariable += 1;
如果你把它放在一个非静态成员上,会发生什么?
我相信这是被忽略的:
class A { [ThreadStatic] public int a; } [Test] public void Try() { var a1 = new A(); var a2 = new A(); a1.a = 5; a2.a = 10; a1.a.Should().Be.EqualTo(5); a2.a.Should().Be.EqualTo(10); }
另外值得一提的是,与普通的静态字段相比, ThreadStatic
不需要任何同步机制(因为状态不是共享的)。