天天看點

《C#多線程程式設計實戰(原書第2版)》——1.10 使用C#中的lock關鍵字

本節書摘來自華章出版社《c#多線程程式設計實戰(原書第2版)》一書中的第1章,第1.10節,作者(美)易格恩·阿格佛溫(eugene agafonov),黃博文 黃輝蘭 譯,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

本節将描述如何確定當一個線程使用某些資源時,同時其他線程無法使用該資源。我們将了解該情況的必要性及整個線程安全概念都包含什麼。

為了學習本節,你需要安裝visual studio 2015。除此之外無需其他準備。本節的源代碼放置在booksampleschapter1recipe9目錄中。

請執行以下步驟來了解如何使用c#中的lock關鍵字:

1.啟動visual studio 2015。建立一個c#控制台應用程式項目。

2.在program.cs檔案中加入以下using指令:

《C#多線程程式設計實戰(原書第2版)》——1.10 使用C#中的lock關鍵字

3.在main方法下面加入以下代碼片段:

《C#多線程程式設計實戰(原書第2版)》——1.10 使用C#中的lock關鍵字
《C#多線程程式設計實戰(原書第2版)》——1.10 使用C#中的lock關鍵字
《C#多線程程式設計實戰(原書第2版)》——1.10 使用C#中的lock關鍵字

4.在main方法中加入以下代碼片段:

《C#多線程程式設計實戰(原書第2版)》——1.10 使用C#中的lock關鍵字
《C#多線程程式設計實戰(原書第2版)》——1.10 使用C#中的lock關鍵字

5.運作程式。

當主程式啟動時,建立了一個counter類的對象。該類定義了一個可以遞增和遞減的簡單的計數器。然後我們啟動了三個線程。這三個線程共享同一個counter執行個體,在一個周期中進行一次遞增和一次遞減。這将導緻不确定的結果。如果運作程式多次,則會列印出多個不同的計數器值。結果可能是0,但大多數情況下則不是0。

這是因為counter類并不是線程安全的。當多個線程同時通路counter對象時,第一個線程得到的counter值10并增加為11。然後第二個線程得到的值是11并增加為12。第一個線程得到counter值12,但是遞減操作發生前,第二個線程得到的counter值也是12。然後第一個線程将12遞減為11并儲存回counter中,同時第二個線程進行了同樣的操作。結果我們進行了兩次遞增操作但是隻有一次遞減操作,這顯然不對。這種情形被稱為競争條件(race condition)。競争條件是多線程環境中非常常見的導緻錯誤的原因。

為了確定不會發生以上情形,必須保證當有線程操作counter對象時,所有其他線程必須等待直到目前線程完成操作。我們可以使用lock關鍵字來實作這種行為。如果鎖定了一個對象,需要通路該對象的所有其他線程則會處于阻塞狀态,并等待直到該對象解除鎖定。這可能會導緻嚴重的性能問題,在第2章中将會進一步學習該知識點。