1. 程式人生 > 實用技巧 >C# Lock 機制

C# Lock 機制

Lock 互斥鎖

定義:lock 確保當一個執行緒位於程式碼的臨界區時,另一個執行緒不進入臨界區。如果其他執行緒試圖進入鎖定的程式碼,則它將一直等待(即被阻止),直到該物件被釋放。

Monitor 方法是靜態的,不需要生成Monitor 類的例項就可以直接呼叫它們。在.NET Framework 中,每個物件都有一個與之關聯的鎖,物件可以得到並釋放它以便於在任意時間只有一個執行緒可以訪問物件例項變數和方法。

Lock語句可以說就是通過Monitor.Enter()和Monitor.Exit()實現的。

當Lock(lockInstance){}結構開始執行時呼叫Monitor.Enter(lockInstance)鎖定lockInstance臨界區,當該結構執行結束,呼叫monitor.Exit(lockInstance)釋放lockInstance臨界區。

原理:對於任何一個物件來說,它在記憶體中的第一部分放置的是所有方法的地址,第二部分放著一個索引,這個索引指向CLR中的SyncBlock Cache區域中的一個SyncBlock。當你執行Monitor.Enter(Object)時,如果object的索引值為負數,就從SyncBlock Cache中選取一個SyncBlock,將其地址放在object的索引中。這樣就完成了以object為標誌的鎖定,其他的執行緒想再次進行Monitor.Enter(object)操作,將獲得object的已經為正值的索引,然後就等待。直到索引變為負數,即呼叫Monitor.Exit(object)將索引變為負數,等待的執行緒開始執行

注意:

1.lock不能鎖定空值,但Null是不需要被釋放的。
2.lock不能鎖定string型別,雖然它也是引用型別的。因為字串型別被CLR“暫留”。即整個程式中任何給定字串都只有一個例項,具有相同內容的字串都代表著同一個例項。因此,只要在應用程式程序中的任何位置處具有相同內容的字串上放置了鎖,就將鎖定應用程式中與該字串具有相同內容的字串。因此,最好鎖定不會被暫留的私有或受保護成員。

當我們使用執行緒的時候,效率最高的方式當然是非同步,即各個執行緒同時執行,其間不相互依賴和等待。但當不同的執行緒都需要訪問某個資源的時候,就需要同步機制了,也就是說當對同一個資源進行讀寫的時候,我們要使該資源在同一時刻只能被一個執行緒操作,以確保每個操作都是有效即時的,也即保證其操作的原子性。lock是C#中最常用的同步方式,格式為lock(objectA){codeB} 。

lock(objectA){codeB} 看似簡單,實際上有三個意思,這對於適當地使用它至關重要:
1. objectA被lock了嗎?沒有則由我來lock,否則一直等待,直至objectA被釋放。
2. lock以後在執行codeB的期間其他執行緒不能呼叫codeB,也不能使用objectA。
3. 執行完codeB之後釋放objectA,並且codeB可以被其他執行緒訪問。

private static readonly object SequenceLock = new object();

public string XMethod(string params)
{
    // ...
    lock (SequenceLock)
    {
    //互斥內容
    //...
    }
}