[ThreadStatic]
属性如何起作用?我以为编译器会发出一些IL来填充/检索TLS中的值,但查看反汇编似乎并没有达到该水平。
作为后续措施,如果将其放在非静态成员上会怎样?我们有一个开发人员犯了这个错误,而编译器甚至没有发出警告。
更新资料
在这里回答的第二个问题:用静态C#修改ThreadStatic
[ThreadStatic]
属性如何起作用?我以为编译器会发出一些IL来填充/检索TLS中的值,但查看反汇编似乎并没有达到该水平。
作为后续措施,如果将其放在非静态成员上会怎样?我们有一个开发人员犯了这个错误,而编译器甚至没有发出警告。
更新资料
在这里回答的第二个问题:用静态C#修改ThreadStatic
Answers:
在.NET jit编译器中,线程静态的实现语义低于IL级别。像VB.NET和C#一样向IL发出的编译器不需要了解有关Win32 TLS的任何知识,就可以发出可以读取和写入具有ThreadStatic属性的变量的IL代码。就C#而言,变量没有什么特别的-它只是读写内容的位置。它具有属性的事实与C#无关。C#仅需要知道针对该符号名称发出IL读或写指令。
“繁重的工作”由核心CLR完成,它负责使IL在特定的硬件体系结构上工作。
这也可以解释为什么将属性放在不适当的(非静态)符号上不会引起编译器的反应。编译器不知道该属性需要什么特殊语义。但是,诸如FX / Cop之类的代码分析工具应该对此有所了解。
另一种查看方式:CIL定义了一组存储范围:静态(全局)存储,成员存储和堆栈存储。TLS不在该列表中,很可能是因为TLS不必在该列表中。如果用符号TLS属性标记符号后,如果IL读和写指令足以访问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
,与普通静态字段相比,它不需要任何同步机制(因为不共享状态)。
"MyClass.myVariable"
,不是吗?
TransactionScope
它们存储各种各样的东西在那里的范围(referencesource.microsoft.com/#System.Transactions/System/...)
[ThreadStatic]在每个线程中创建同一变量的隔离版本。
例:
[ThreadStatic] public static int i; // Declaration of the variable i with ThreadStatic Attribute.
public static void Main()
{
new Thread(() =>
{
for (int x = 0; x < 10; x++)
{
i++;
Console.WriteLine("Thread A: {0}", i); // Uses one instance of the i variable.
}
}).Start();
new Thread(() =>
{
for (int x = 0; x < 10; x++)
{
i++;
Console.WriteLine("Thread B: {0}", i); // Uses another instance of the i variable.
}
}).Start();
}
标[ThreadStatic]
有的字段是在线程本地存储上创建的,因此每个线程都有其自己的字段副本,即字段的范围是线程本地的。
TLS字段可通过gs / fs段寄存器进行访问.OS内核使用这些段来访问特定于线程的内存.NET编译器不会发出任何IL来填充/检索TLS中的值。它是由OS内核完成的。