2010-07-05 44 views
1

考慮下面的代碼:C#4.0 BCL SpinLock的旋轉/阻止何時無法鎖定?

... 
private static SpinLock logLock = new SpinLock(false); 
... 

private static void ThreadFunc() 
{ 
    bool lockTaken = false; 
    logLock.Enter(ref lockTaken) 
    { 
     try 
     { 
      // do stuff with during an acquired SpinLock 
     } 
     finally 
     { 
      logLock.Exit(); 
     } 
    } 
} 

如果輸入塊「失敗」,因爲它接收到一個假的鎖被收購,確實當前線程旋像一個自旋鎖和等待,直到它可以獲取它,或者這是塊簡單繞過,線程失去了?

謝謝,

斯科特

回答

2

自旋鎖由定義導致線程在等待獲取一個鎖而不是阻止旋轉。如果Enter不能獲取鎖,則Enter不會「失敗」,它只是等待。

Enter可能無法拋出異常的唯一情況是使用新的SpinLock()或新的SpinLock(true)激活線程所有權。在這種情況下,當一個線程嘗試獲取它已經擁有的鎖時會引發異常。在你的情況下,這永遠不會發生,因爲你創建了跟蹤禁用的鎖(SpinLock(false))。如果線程試圖重新獲得鎖定,它將只會發生死鎖。

這在SpinLock.Enter方法的文檔中有描述。

+0

謝謝!你已經證實了我的懷疑,以及VS 2010中的線程調試器。 – 2010-07-05 11:09:28

1

A SpinLock基本上只是一個嘗試將變量設置爲特定值的循環。

你可以考慮它的實現如下:

public struct SpinLock 
{ 
    private volatile bool _Locked; 

    public void Acquire() 
    { 
     while (_Locked) 
      ; 
     _Locked = true; 
    } 

    public void Release() 
    { 
     _Locked = false; 
    } 
} 

(當然,上面的代碼不是線程安全的,我知道那不是的類的方法簽名,它只是一個僞代碼變種,以顯示它在做什麼)

所以是的,如果SpinLock已經處於鎖定狀態,試圖獲取它將旋轉,直到它變得可用。

此外,請注意,默認情況下(如您的示例中),結構不記錄誰擁有鎖。這意味着如果一個線程試圖獲得兩次鎖定,它將在第二次嘗試時自己死鎖。

SpinLock的目的是成爲一個用戶級鎖,開銷很小。它不會增加GC壓力,也不會分配任何內核同步對象,它只是一個具有幾個字段的結構。

+0

謝謝!這類似於我在閱讀的書中看到的「手卷」示例,就在他們討論實際.NET 4.0 BCL SpinLock之前。這加強了我需要知道的東西。 – 2010-07-05 11:08:51