淺析 C# Lock

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)//加鎖  註釋掉

執行結果如下:加鎖

不加鎖:

 

以上爲執行結果,可以看出,加鎖與不加鎖的情況下,執行結果顯然不同。

歡迎大家指正。感謝。

更多博文,請點擊下方鏈接,共同學習,共同進步。

C#設計模式,工廠三兄弟

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章