ThreadStaticAttribute 的作用是告诉CLR,它标记的静态字段的存取是依赖当前线程,而独立于其他线程的。
例如:
class MyClass{
[ThreadStatic] static public string threadvalue;
}
MyClass 中的threadvalue就是一个线程静态字段 。 如果一个程序中同时有多个线程同时访问这个字段,则每个线程访问的都是独立的threadvalue 。例如线程1设置它为”hello”,然后线程2设置它为”world”,最后线程1读取它的时候,得到的是”hello”。
基于这个,线程静态字段有以下特征:
- 它是静态的字段。所以不需要MyClass的实例,直接用 MyClass.threadvalue的形式来访问就可以了。
- 它的存取是根据线程来指定内存位置的,所以它的存取速度较慢。
- 访问线程静态字段不可能发生线程不同步问题。因为虽然语意上不同线程访问的是同一字段,但实际上不同线程访问的是不同的内存块。
- 一条线程不可能访问到另外一条线程上的线程静态字段。就算你得到另外一条线程的System.Threading.Thread 对象的引用也不行。
但是,使用线程静态字段要注意:
- 字段上的初始化语句在类的静态构造方法中执行。所以语句只执行一句。其他线程再访问这个字段时,为字段的类型的默认值。
- 如果不同线程上的字段都引用同一对象,那么不代表该对象是线程同步的。因为[ThreadStatic]指的是字段是隔离的。但是它引用的对象则不被[ThreadStatic]控制。
如果你知道 System.Runtime.Remoting.Messaging.Context (以下简称MContext)
那么MContext和线程静态字段有什么不同呢?
- 他们可以说都是与当前线程相关的。但是他们不是同一个东西。
- MContext是基于名称的,可以根据名称储存不同的数据。而ThreadStatic不会有名称冲突。
- ThreadStatic 是CLR内部实现的。而 MContext 是附属在 System.Threading.Thread 对象的一个字典。
- 线程静态字段的存取速度比MContext的快
- MContext被叫做逻辑线程上下文数据。它的数据会在异步调用的时候复制到另外一条线程中。而线程静态字段是不会被复制的。(例如 eventHandlerInst.BeginInvoke(...)时,在新的线程中,就拥有原线程上MContext的数据。在eventHandlerInst.EndInvoke执行时,新线程上的MContext上的数据就会还原到调用EndInvoke的线程上.这个在以后讲到Remoting时会详细说)
- System.Web.HttpContext.Current 是用 MContext 实现的。