天天看點

Lock關鍵字的用法

 Lock 關鍵字可確定當一個線程位于代碼的臨界區時,另一個線程不會進入該臨界區。如果其他線程嘗試進入鎖定的代碼,則它将一直等待(即被阻止),直到該對象被釋放。

 Lock關鍵字用途主要是解決多線程下限制同時通路同一個對象。

摘要: 一直以來對于lock關鍵字的用法都存有疑惑,也從網上看到很多關于他的資料包括MSDN,無奈MSDN講述的真是讓人上火。今天決定小小研究一下一直都知道lock是鎖定某一變量進而實作對某一代碼段的獨占執行。但是對于lock(t ...

一直以來對于lock關鍵字的用法都存有疑惑,也從網上看到很多關于他的資料包括MSDN,無奈MSDN講述的真是讓人上火。今天決定小小研究一下

一直都知道lock是鎖定某一變量進而實作對某一代碼段的獨占執行。

但是對于lock(this)、lock(typeof(類名))、lock(字元串)、lock(公有變量) lock(私有變量) 有什麼不同 卻很是模糊

我假定了這樣一種場景:某個時刻,隻允許一個客戶在打電話

定義一個客戶類

代碼1:(lock(this))

///定義一個Custmer類,要求某一時間,隻允許一個客戶在打電話 

public class Custmer

    {

        public Custmer()

        {

        }

        public Custmer(string name)

            _name = name;

    ///某一時刻隻允許一個客戶在打電話

        public void getPhone()

            lock (this)

            {

                    for (int i = 0; i < 10; i++)

                    {

                        Console.WriteLine(Thread.CurrentThread.Name+"正在跟客戶在通話");

                        Thread.Sleep(1000);

                    }

            }

    }

在主函數中調用,先執行個體化一個Custmer 執行個體

  static void Main(string[] args)

            Custmer c=new Custmer();

            Thread t1 = new Thread(new ThreadStart(c.getPhone));

            t1.Name = "t1";

            Thread t2 = new Thread(new ThreadStart(c.getPhone));

            t2.Name = "t2";

            t1.Start();

            t2.Start();

            Console.Read();

可以預先分析一下結果,因為用的是lock(this),而this這時候代表的是執行個體c,當其中一個線程在使用的時候,另一個線程是不能使用的。也就是說,結果應該是其中一個線程先使用,另一個再使用,而不是交替使用。

運作結果1:

<a href="http://www.189works.com/data/attachment/portal/201012/22/143540uzuobk8ku2zk4tko.jpg" target="_blank"></a>

跟預想的結果一樣,但是如果是多個客戶執行個體呢,結果有怎樣

代碼2:

代碼

            //這裡我執行個體化了兩個客戶類

            Custmer c2 = new Custmer();

           //線程1去接通c的電話

           //線程2去接通c2的電話

            Thread t2 = new Thread(new ThreadStart(c2.getPhone));

再預想一下結果,對于線程t1,跟客戶c接通電話,此時lock(this)中的this是目前執行個體c。同理,對于線程t2,this是執行個體c2.這樣lock(this)鎖定的是不同的對象,是以無法達到某一時刻,隻有一個客戶在電話。也就是說,兩個線程會交替執行。

執行結果2:

<a href="http://www.189works.com/data/attachment/portal/201012/22/143543jmnk8fcmpjja2j32.jpg" target="_blank"></a>

與預想結果一樣。從這裡我們知道,lock(this)存在多個執行個體間互斥不能實作的問題,原因在于this指向的是不同的執行個體

另外在有的地方說lock(this)可能會造成死鎖,所謂的死鎖,無非就是一個線程長期鎖定this不釋放。 可能是lock鎖定的代碼段是個死循環,也可能你在一個死循環裡調用lock鎖定的代碼段。總之是沒有釋放鎖定對象。

Lock(typeof(類名))

我重新定義了一個sales類,用來在Customer類中鎖定它

sales類

public class sales

        public sales(string name)

        string _name;

        public string Name

            get { return _name; }

            set { _name = value; }

Customer類改寫如下:

        }      

            lock (typeof(sales))//關鍵是這裡

我們在主函數中,調用如Lock(this)的單個執行個體的情況,我們會發現,實作了互斥。多個執行個體的情況也實作了互斥。但是又有了新的問題。因為我們鎖定的是類本身,是以如果有一個地方是在使用類,那麼其他地方就不能使用該類,這樣的限制過于苛刻。

3.Lock(字元串)

這個就更好玩了,他是實作了絕對的互斥。隻要字元串内容相同,就能引起程式挂起。原因是在.NET中,字元串會被暫時存放,如果兩個變量的字元串内容相同的話,.NET會把暫存的字元串對象配置設定給該變量。是以如果有兩個地方都在使用lock(字元串)的話,它們實際鎖住的是同一個對象。

那我們看一下代碼和執行結果

代碼:

    public class Custmer

        string flag = "ATually";//定義了一個字元串變量

            lock (flag)//關鍵是這裡

多個執行個體的情況下的執行結果也實作了互斥。

對于Lock(共有變量)和Lock(私有變量)基本效果都一樣,但是都會出現對于多個執行個體都無法實作互斥。

是以,微軟推薦使用私有靜态變量作為鎖定的變量。但是個人覺得與鎖定類和鎖定字元串 沒有什麼不同。

以上隻是個人淺見,如有錯的地方,請不吝賜教,謝謝。