.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是允许多次修改,这个是需要注意的地方。

posted on 2010-08-09 13:51  Kain  阅读(2610)  评论(1编辑  收藏  举报

导航