臨界區:當兩個線程競爭同一資源時,如果對資源的訪問順序敏感,就稱存在競態條件。導致競態條件發生的代碼區稱作臨界區。
臨界區線程同步適用范圍:它只能同步一個進程中的線程,不能跨進程同步。一般用它來做單個進程內的代碼快同步,效率比較高。
在.Net中有Monitor、Lock等方式是以臨界區的方式來實現線程同步的,我們看一下兩者的具體示例。
1、Lock Lock關鍵字將代碼塊標記為臨界區,方法是獲取指定對象的互斥鎖,執行語句,然后釋放鎖,這樣其它線程就可以接着獲取鎖來進入臨界區。
Lock關鍵字保證了臨界資源在同一時刻只能有唯一一個線程訪問,一旦有線程獲取互斥鎖,進入臨界區,其它線程訪問時就會被掛起,直到當前線程釋放鎖。
private static object lockObj = new object(); lock(lockObj) { //操作公共資源 }
對於任何一個引用對象都存在一個索引,該索引指向CLR中SyncBlock Cache中的SyncBlock。當執行lock(object)時,如果object索引值為負數,就從SyncBlock Cache
中取出一個SyncBlock,存入object索引值,這樣object索引值就變成了正數。當有其它線程再進入時lock(object)時發現object索引值不為負,責掛起等待,直到object索引
值變為負數。
使用lock應注意
1)lock不能鎖定null值
2)lock不能鎖定string類型的值,雖然它是引用類型,旦字符串類型被CLR暫留
3)lock鎖定的必須是引用類型,不能是值類型
4)lock避免鎖定public對象,因為公開的對象可能被其它類進行修改,很可能導致死鎖。如lock(this)時,當前對象的公開屬性值被修改后,會造成線程安全問題
2、Monitor的用法
Monitor類使用Enter(object)和Exit(object)來標示臨界區,事實上lock使用的原理就是Monitor。當lock開始是調用就是monitor.Enter(object),當lock結束時
則調用monitor.Exit(object)釋放object鎖。
