.net 4.0 中对多线程新特性(二)
上篇已经简单介绍了.net 4.0中Lazy<T>类,通过Lazy<T>我们可以很容易的延迟初始化一些对象。如果我们需要在多线程环境下建立一些线程级别应用可以使用ThreadLocal<T>。在MSND中我们可以了解到除了Dispose之外,ThreadLocal<T> 的所有公共和受保护的成员都是线程安全的,可从多个线程同时使用。Value 和 IsValueCreated 属性返回的值是特定的线程在其访问该属性。
在4.0之前为了实现线程级别存储会使用ThreadStatic标签来标识某个变量是线程级别存储的,例如:
class Program { static void Main(string[] args) { for (int i = 0; i < 5; i++) { var thread = new Thread( new ThreadStart( ()=> { using( var scope = new ThreadStaticScope() ) { Console.WriteLine("Thread Id:{0}",ThreadStaticScope.Current.Value); } }) ); thread.Start(); } Console.Read(); } } public class ThreadStaticScope:IDisposable { [ThreadStatic] static ThreadStaticScope __inc; public ThreadStaticScope() { Value = Thread.CurrentThread.ManagedThreadId; __inc = this; } public int Value { get; private set; } public static ThreadStaticScope Current { get { return __inc; } } public void Dispose() { __inc = null; GC.SuppressFinalize(this); } }
输出结果:
Thread Id:11
Thread Id:12
Thread Id:13
Thread Id:14
Thread Id:15
从输出结果可以看到每个线程都是独享一个ThreadStaticScope.
换作ThreadLocal<T>可以非常方便的实现同样的效果。
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
var thread = new Thread( new ThreadStart( ()=>
{
using (var scope = new ThreadLocalScope())
{
Console.WriteLine("Thread Id:{0}", ThreadLocalScope.Current.Value);
}
}) );
thread.Start();
}
Console.Read();
}
}
public class ThreadLocalScope:IDisposable
{
static ThreadLocal<ThreadLocalScope> __inc = new ThreadLocal<ThreadLocalScope>( );
public ThreadLocalScope()
{
Value = Thread.CurrentThread.ManagedThreadId;
__inc.Value = this;
}
public int Value
{
get;
private set;
}
public static ThreadLocalScope Current
{
get { return __inc.Value; }
}
public void Dispose()
{
__inc.Dispose();
GC.SuppressFinalize(this);
}
}
输出结果:
Thread Id:11
Thread Id:12
Thread Id:13
Thread Id:14
Thread Id:15
利用好ThreadLazy可以非常方便的实现一些以前表较复杂的实现。Lazy<T>中由于多线程共享同一个实例因此其value值一旦初始化之后是不允许修改的,但是ThreadLazy是允许多次修改,这个是需要注意的地方。