c中lock的用法
下面小編就跟你們詳細介紹下c中lock的用法的用法,希望對你們有用。
c中lock的用法的用法如下:
本文例項講述了C#中lock的用法。分享給大家供大家參考。具體分析如下:
lock 關鍵字可以用來確保程式碼塊完成執行,而不會被其他執行緒中斷。這是通過在程式碼塊執行期間為給定物件獲取互斥鎖來實現的。
先來看看執行過程,程式碼示例如下:
lock 語句用於獲取某個給定物件的互斥鎖,執行一個語句,然後釋放該鎖。
lock-statement:(lock 語句:)
複製程式碼 程式碼如下:
lock(expression) embedded-statement(lock ( 表示式 ) 嵌入語句)
lock 語句的表示式必須表示一個引用型別的值。永遠不會為 lock 語句中的表示式執行隱式裝箱轉換,因此,如果該表示式表示的是一個值型別的值,則會導致一個編譯時錯誤。
下列形式的 lock 語句:
複製程式碼 程式碼如下:
lock (x) ...
(其中 x 是一個引用型別的表示式)完全等效於
複製程式碼 程式碼如下:
r(x);
try {
...
}
finally {
(x);
}
不同的只是:實際執行中 x 只計算一次。
當一個互斥鎖已被佔用時,在同一執行緒中執行的程式碼仍可以獲取和釋放該鎖。但是,在其他執行緒中執行的程式碼在該鎖被釋放前是無法獲得它的。
一個類的 物件可以方便地用來當作關於該類的靜態方法的互斥鎖。例如:
複製程式碼 程式碼如下:
class cache
{
public static void add(object x) {
lock (typeof(cache)) {
...
}
}
public static void remove(object x) {
lock (typeof(cache)) {
...
}
}
}
假設執行緒a先執行,執行緒b稍微慢一點。執行緒a執行到lock語句,判斷obj是否已申請了互斥鎖,判斷依據是逐個與已存在的鎖進行renceequals比較(此處未加證實),如果不存在,則申請一個新的互斥鎖,這時執行緒a進入lock裡面了。
這時假設執行緒b啟動了,而執行緒a還未執行完lock裡面的程式碼。執行緒b執行到lock語句,檢查到obj已經申請了互斥鎖,於是等待;直到執行緒a執行完畢,釋放互斥鎖,執行緒b才能申請新的互斥鎖並執行lock裡面的程式碼。
接下來說一些該lock什麼物件。
為什麼不能lock值型別,比如lock(1)呢?lock本質上r,r會使值型別裝箱,每次lock的是裝箱後的物件。lock其實是類似編譯器的語法糖,因此編譯器直接限制住不能lock值型別。
退一萬步說,就算能編譯器允許你lock(1),但是renceequals(1,1)始終返回false(因為每次裝箱後都是不同物件),也就是說每次都會判斷成未申請互斥鎖,這樣在同一時間,別的執行緒照樣能夠訪問裡面的程式碼,達不到同步的效果。同理lock((object)1)也不行。
那麼lock("xxx")字串呢?msdn上的原話是:
鎖定字串尤其危險,因為字串被公共語言執行庫 (clr)“暫留”。 這意味著整個程式中任何給定字串都只有一個例項,就是這同一個物件表示了所有執行的應用程式域的所有執行緒中的該文字。因此,只要在應用程式程序中的任何位置處具有相同內容的字串上放置了鎖,就將鎖定應用程式中該字串的所有例項。
通常,最好避免鎖定 public 型別或鎖定不受應用程式控制的物件例項。例如,如果該例項可以被公開訪問,則 lock(this) 可能會有問題,因為不受控制的程式碼也可能會鎖定該物件。這可能導致死鎖,即兩個或更多個執行緒等待釋放同一物件。出於同樣的原因,鎖定公共資料型別(相比於物件)也可能導致問題。而且lock(this)只對當前物件有效,如果多個物件之間就達不到同步的效果。
lock(typeof(class))與鎖定字串一樣,範圍太廣了。
某些系統類提供專門用於鎖定的成員。例如,array 型別提供 syncroot。許多集合型別也提供 syncroot。
而自定義類推薦用私有的只讀靜態物件,比如:
複製程式碼 程式碼如下:
private static readonly object obj = new object();
為什麼要設定成只讀的呢?這時因為如果在lock程式碼段中改變obj的值,其它執行緒就暢通無阻了,因為互斥鎖的
物件變了,renceequals必然返回false。
希望本文所述對大家的C#程式設計有所幫助。