2013-05-21 20 views
1

我需要在一段時間只有一個線程運行代碼(單個資源鎖定)。Lock語句如何確定授予對象訪問的順序?

lock(object)聲明在C#中允許這樣做。但是,它並不保留鎖的請求順序。

例如,考慮下面在那裏編號線程試圖在訂單上掛鎖鎖定100個threadstarts:

for (int i = 0; i < 100; i++) 
      { 

      (new Thread(delegate(object index) 
       { 
        int name = (int) index; 
        byte[] len = new byte[2]; 

        Console.WriteLine(string.Format("Thread:{0} going for lock. ", 
         name)); 
        lock (padlock) 
        { 

        rnd.GetBytes(len); 
        ushort l = BitConverter.ToUInt16(len, 0); 
        Console.WriteLine(string.Format("Thread:{0} sleeping: {1}", 
         name, l)); 
        Thread.Sleep(l); 
        } 
      })).Start(i); 

的訪問的實際給予不完美順序(1-> 100)或NOT FIFO 。但是,似乎確實有一個「提早出局」的EIEO模式(可能由堆運行?)。

問題是:什麼決定了鎖授予順序能不能在不捱餓不吉利的線程依賴?

更新this answer解釋它。這裏是相關報價(喬·達菲的在Windows併發編程):

由於顯示器使用內核對象的內部,他們表現出相同的 大致-FIFO行爲的OS同步機制也 展覽(在前面的章節中描述)。顯示器是不公平的,所以如果 另一個線程嘗試之前喚醒等待 線程試圖獲取鎖獲取鎖,偷偷摸摸線程被允許 獲取鎖。

+0

http://stackoverflow.com/q/5111779/34397的http://計算器.COM/q /34397分之4228864 – SLaks

+1

@SLaks在第二個的喬恩斯基特答案呈現此爲重複。 – MandoMando

+0

哈,顯然你在和我同時看着喬的報價。 –

回答

3

什麼決定了鎖授予順序

沒有在規格定義的順序。你不能依賴任何訂單。

可它不會餓死一個不吉利的線程來依靠?

不需要。如果您的應用程序存在潛在問題,則需要手動管理它。


另請注意,由於幾種不同的原因,線程運行的順序未確定。你知道所有的線索都將以特定的順序開始,但一旦他們開始,你就不知道他們將如何安排。他們可以以任何順序擊中lock區塊。即使它是基於他們什麼時候碰到lock,它仍然是未定義的。

+1

擴展了一點:如果你想精確控制什麼時候運行,你通常不需要一個線程。你最好把線索想象成試圖強化墨菲定律,只要他們非常好的請求就跑,總是在錯誤的時間。 – cHao

+0

@ cHao不,這些是來自網絡的請求,只是不想讓它們餓死。如果操作系統需要一點賄賂和偏袒,那也沒關係。似乎這些日子到處都是。 – MandoMando

4

塞維維的答案當然是正確的。一些額外的細節:

什麼決定了鎖定授予順序?

最終,該操作系統。

它可以依靠不餓不幸的線程?

飢餓是不可能的,但可能的。如果你不能忍受飢餓的小機會,你需要的東西比鎖更復雜。

我還注意到,鎖是「不公平的」,因爲你可以在鎖中有一個線程,等待的8個線程,鎖中的線程離開,還有第十個線程根本沒有等待請​​求鎖,得到它,有效地「切割線」。喬給出了爲什麼現在的Windows使用的「不公平」在這裏鎖定分配策略,如果這個問題的利益,你一個有趣的分析:

http://www.bluebytesoftware.com/blog/PermaLink,guid,e40c2675-43a3-410f-8f85-616ef7b031aa.aspx

+0

關於不公平的有趣的一點。我一直以爲窗戶是不公平的(不是道德的)。在複雜的同步隊列之外是否存在「公平的」鎖定對象? – MandoMando

+0

@MandoMando:我不知道任何人,但我遠離這個話題的專家。 –

+0

@MandoMando你可以建立一個公平的制度出了不公平的制度的,如果你是適當的動機(只需創建一個'隊列'和同步訪問,作爲一個簡單的例子),它只是降低了應用程序的吞吐量的結果那開銷。由於這很少成爲問題,所以吞吐量通常比公平性「值得更多」。 – Servy

相關問題