Lock的定義以及概念
實現線程同步的第一種方式是我們經常使用的lock關鍵字,它將包圍的語句塊標記爲臨界區,這樣一次只有一個線程進入臨界區並執行代碼。下面第一段的幾行代碼是關於lock關鍵字的使用方式,但更重要的是我們可以通過這個例子來看到lock關鍵字的本質。第二段是這個方法的IL指令集,從中可以看到lock其實也是一個語法糖,它的內部實現是採用了監視器Monitor。
lock 關鍵字將語句塊標記爲臨界區,方法是獲取給定對象的互斥鎖,執行語句,然後釋放該鎖。
模擬應用場景
用多個線程同時操作一個方法,這裏模擬存錢的場景。多用戶(線程)操作存錢的操作。(代碼如下:)
測試使用Winform程序,一個按鈕,一個RichTextBox
代碼如下:
private static object locker = new object();//定義對象
public static int sum = 0; //總賬戶餘額
//存錢的業務邏輯
private void addToSum()
{
lock (locker)//加鎖
{
while (true)
{
richTextBox1.Invoke(new Action<string>((x) =>
{
richTextBox1.AppendText("正在存錢" + x);
sum += 100;
//Thread.Sleep(TimeSpan.FromMilliseconds(2000)); //此處是佔用了主線程,會導致UI卡着不動,刷新遲緩。所以卸載Invoke外層去了,不信可以用下面的if做下測試
richTextBox1.AppendText("當前餘額爲" + sum + "\r\n");
System.Windows.Forms.Application.DoEvents();
}), Thread.CurrentThread.Name);
// if (sum >= 1000) { break; }
Thread.Sleep(TimeSpan.FromMilliseconds(2000));
}
}
}
下面來操作這個賬戶,聲明多個線程來操作這個方法。看下執行效果。
private void button1_Click(object sender, EventArgs e)
{
Thread th1 = new Thread(addToSum);
th1.Name = "th1name";//指定線程名稱,方便區分
Thread th2 = new Thread(addToSum);
th1.Start();
Thread.Sleep(1000);
th2.Start();
}
分兩種情況來解析
第一種是,加鎖的情況下
lock (locker)//加鎖
第二種是將這段代碼塊註釋掉,分別看下執行效果。
//lock (locker)//加鎖 註釋掉
執行結果如下:加鎖
不加鎖:
以上爲執行結果,可以看出,加鎖與不加鎖的情況下,執行結果顯然不同。
歡迎大家指正。感謝。
更多博文,請點擊下方鏈接,共同學習,共同進步。