.NET Framework 提供了很多System.Threading,System.EnterpriseService 和 System.Runtime.Compiler 命名空間中的很多類來幫助程序員開發線程安全代碼。下表簡要地描述了.NET Framework 中的一些同步類。
MethodImplAttribute 類
正如System.Runtime.CompilerServices 命名空間名字所顯式的,這個命名空間中包含影響CLR 運行時行為的屬性。MethodImplAttribute是通知CLR某個方法是如何實現的眾多屬性之一。MethodImplAttribute 構造函數之一以MethodImplOptions作為參數。MethodImplOptions枚舉有一個保證在任意時間僅有一個線程訪問方法的同步字段名。這類似於我們在之前例子中用的lock 關鍵字。下面的MI.cs 顯示了你可以怎樣使用這個屬性來同步一個方法:
/************************************* /* Copyright (c) 2012 Daniel Dong * * Author:oDaniel Dong * Blog:o www.cnblogs.com/danielWise * Email:o guofoo@163.com * */ using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Runtime.CompilerServices; namespace MethodImpl { class MI { //This attribute locks the method for use //by one and only one thread at a time. [MethodImpl(MethodImplOptions.Synchronized)] public void doSomeWorkSync() { Console.WriteLine("doSomeWorkSync()" + "--Lock held by Thread " + Thread.CurrentThread.GetHashCode()); //When a thread sleeps, it still holds the lock Thread.Sleep(5000); Console.WriteLine("doSomeWorkSync()" + "--Lock released by Thread " + Thread.CurrentThread.GetHashCode()); } //This is a non synchronized method public void doSomeWorkNoSync() { Console.WriteLine("doSomeWorkNoSync()" + "--Entered Thread is " + Thread.CurrentThread.GetHashCode()); Thread.Sleep(5000); Console.WriteLine("doSomeWorkNoSync()" + "--Leaving Thread is " + Thread.CurrentThread.GetHashCode()); } static void Main(string[] args) { MI m = new MI(); //Delegate for Non-Synchronous operation ThreadStart tsNoSyncDelegate = new ThreadStart(m.doSomeWorkNoSync); //Delegate for Synchronous operation ThreadStart tsSyncDelegate = new ThreadStart(m.doSomeWorkSync); Thread t1 = new Thread(tsNoSyncDelegate); Thread t2 = new Thread(tsNoSyncDelegate); t1.Start(); t2.Start(); Thread t3 = new Thread(tsSyncDelegate); Thread t4 = new Thread(tsSyncDelegate); t3.Start(); t4.Start(); Console.ReadLine(); } } }
輸出結果類似以下(不同計算機的輸出結果可能非常不同):
在上面代碼片段中,MI 類有兩個方法:doSomeWorkSync() 和 doSomeWorkNoSync() 。MethodImpl 屬性被應用到doSomeWorkSync() 方法上來同步它,而doSomeWorkNoSync() 方法未作改動,仍然可以在同一時間被多個線程訪問。在Main() 方法中,線程t1 和 t2 訪問非同步訪問,線程t3 和 t4訪問不同方法。使用Thread.Sleep() 方法來保證當一個線程仍然在方法中時另外一個競爭方法可以進入同一個方法。程序的期待行為時線程t1 和 t2 可以同時進入doSomeWorkNoSync()方法, 而僅允許一個線程(t3或t4)進入doSomeWorkSync()方法。如果t1 和 t2 線程優先級一樣,那么線程的執行順序將會是隨機的;.NET Framework 不保證線程執行順序。
如果你仔細看看輸出結果,你將發現線程2(t1)和線程3(t2)在同一時間進入doSomeWorkNoSync() 方法,而一旦線程4(t3)在方法doSomeWorkSync()上獲得鎖的話,線程5(t4)就不允許進入這個方法直到線程4在這個方法上釋放鎖。
下一篇介紹.NET 同步策略…