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(私有變量)基本效果都一樣,但是都會出現對于多個執行個體都無法實作互斥。
是以,微軟推薦使用私有靜态變量作為鎖定的變量。但是個人覺得與鎖定類和鎖定字元串 沒有什麼不同。
以上隻是個人淺見,如有錯的地方,請不吝賜教,謝謝。