寫在前面 前幾時在寫業務代碼的時候,看到有用到lock這個方法的,而我竟然並不知道是做什麼用的,所以查找了許多博客文章,弄懂了百分之七八十,在此做下筆記。 感謝博客 http://www.cnblogs.com/wolf-sun/p/4209521.html 的解說,該篇博客大部分內容源自於此。 l ...
寫在前面
前幾時在寫業務代碼的時候,看到有用到lock這個方法的,而我竟然並不知道是做什麼用的,所以查找了許多博客文章,弄懂了百分之七八十,在此做下筆記。
感謝博客 http://www.cnblogs.com/wolf-sun/p/4209521.html 的解說,該篇博客大部分內容源自於此。
lock
官方MSDN的說法:
lock 關鍵字可確保當一個線程位於代碼的臨界區時,另一個線程不會進入該臨界區。 如果其他線程嘗試進入鎖定的代碼,則它將一直等待(即被阻止),直到該對象被釋放。
lock 關鍵字在塊的開始處調用 Enter,而在塊的結尾處調用 Exit。 ThreadInterruptedException 引發,如果 Interrupt 中斷等待輸入 lock 語句的線程。
通常,應避免鎖定 public 類型,否則實例將超出代碼的控制範圍。
最經常使用的是下麵的代碼段:
private static readonly object objlock = new object(); lock (objlock ) { //要執行的代碼邏輯 }
對於為什麼鎖私有,我覺得博客 http://www.cnblogs.com/wolf-sun/p/4209521.html 上的一個例子寫的很好:
以廁所為例,私有就好比,廁所的鎖只有你能訪問到,而且最好這把鎖不會因為外力而有所改變,別人訪問不到,這樣才能保證你進去了,別人就進不去了,如果是公有的,就好比你蹲位小單間的鎖不是安裝在裡面而是安裝在外邊的,別人想不想進就不是你所能控制的了,這樣也不安全。
在多線程中,每個線程都有自己的資源,但是代碼區是共用的,即每個線程都可以執行相同的函數。這可能帶來的問題就是幾個線程同時執行一個函數,導致數據的混亂,產生不可預料的結果,因此我們必須避免這種情況的發生。
lock是不能鎖值類型。
lock(string)
string也是應用類型,從語法上來說是沒有錯的。
但是鎖定字元串尤其危險,因為字元串被公共語言運行庫 (CLR)“暫留”。
這意味著整個程式中任何給定字元串都只有一個實例,就是這同一個對象表示了所有運行的應用程式域的所有線程中的該文本。
因此,只要在應用程式進程中的任何位置處具有相同內容的字元串上放置了鎖,就將鎖定應用程式中該字元串的所有實例。
通常,最好避免鎖定 public 類型或鎖定不受應用程式控制的對象實例。
例如,如果該實例可以被公開訪問,則 lock(this) 可能會有問題,因為不受控制的代碼也可能會鎖定該對象。
這可能導致死鎖,即兩個或更多個線程等待釋放同一對象。
出於同樣的原因,鎖定公共數據類型(相比於對象)也可能導致問題。
而且lock(this)只對當前對象有效,如果多個對象之間就達不到同步的效果。lock(typeof(Class))與鎖定字元串一樣,範圍太廣了。
寫在最後
總結一下好了:
1、lock的是引用類型的對象,string類型除外。
2、lock推薦的做法是使用靜態的、只讀的、私有的對象。
3、保證lock的對象在外部無法修改才有意義,如果lock的對象在外部改變了,對其他線程就會暢通無阻,失去了lock的意義。
4、學海無涯,不斷補充自己才是最重要的!努力吧