1. 程式人生 > >.NET4.0新特性:多執行緒

.NET4.0新特性:多執行緒

在.net 40中對多執行緒的處理增加了很多新的類以方便多執行緒環境下的程式設計實現,首先需要了解的是兩個非常有用的類Lazy和ThreadLazy,通過這兩個類我們可以很方便實現一個單例模式而不用考慮太多的執行緒安全的問題。

  Lazy:類簡化了執行物件的延遲初始化和例項化的工作。通過以延遲方式例項化物件,可避免在根本不需要的情況下必須建立所有的物件,或者可以將物件的初始化延遲到第一次訪問它們的時候.例如:

class Program
    {
        
public static Lazy<int> __current =new Lazy<int>(() =>
Thread.CurrentThread.ManagedThreadId);

        static void Main(
string[] args)
        {
            
for (int i =0; i <5; i++)
            {
                var thread
=new Thread( new ThreadStart( ()=>
                    {
                        Console.WriteLine(
string.Format("Current Thread Id:{0} Current Value:{1}
"
                                ,Thread.CurrentThread.ManagedThreadId,__current.Value ) );
                    }) );
                thread.Start();
            }
            
            Console.Read();
        }
        
    }

  程式輸出如下:

1

  可以看到__current.Value在不同的執行緒下面的值始終為第一個執行緒的ID,需要注意的是__current.Value屬性一旦被呼叫就會回撥建構函式中傳入的Fun,如果呼叫失敗__current也不會再次呼叫Fun,其__current.IsValueCreated始終為真,__current.Value是不能夠被修改的。通過Lazy可以非常優雅的實現一個簡單的單例:

public class Singleton
    {
        
private Singleton()
        {
        }

        
private static Lazy<Singleton> __inc =new Lazy<Singleton>(() =>new Singleton());

        
public static Singleton Current
        {
            
get { return __inc.Value; }
        }
    }

通過Lazy我們可以很容易的延遲初始化一些物件。如果我們需要在多執行緒環境下建立一些執行緒級別應用可以使用ThreadLocal。在MSND中我們可以瞭解到除了Dispose之外,ThreadLocal 的所有公共和受保護的成員都是執行緒安全的,可從多個執行緒同時使用。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;
        }

        
publicint Value
        {
            
get;
            
privateset;
        }

        
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可以非常方便的實現同樣的效果。

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;
        }

        
publicint Value
        {
            
get;
            
privateset;
        }

        
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