2010-09-10 67 views
14

可能重複:
Re-entrant locks in C#遞歸/嵌套鎖定在C#與鎖聲明

我在這裏看着的StackOverflow和MSDN,不能相信我不能在互聯網上找不到這個問題。

比方說,我有一個私人成員的類,我想以幾種公共方法訪問。這些公共方法將被不同的線程調用,因此需要同步。

public class MyClass 
{ 
    private Object SomeSharedData = new Object(); 

    public void MethodA() 
    { 
     lock(SomeSharedData) { 
      // do something 
      MethodB(); 
     } 
    } 

    public void MethodB() 
    { 
     lock(SomeSharedData) { 
      // do something 
     } 
    } 
} 

注意,治法和方法b可以通過這個類的用戶調用,但治法也叫方法b,從而導致嵌套鎖定狀態。

這是保證安全嗎?換句話說,.NET是否通過引用計數鎖來處理這個問題,這樣當我彈出這些方法時,鎖就會減少?或者.NET在幕後執行一些魔法,它只是忽略源自同一線程的對象上的所有後續鎖?

+3

FYI鎖就是Monitor.Enter Monitor.Exit – 2010-09-10 19:00:39

+0

@Sergey感謝了語法糖,我覺得其實我在我的C#書中讀過一次,但找不到它。 – Dave 2010-09-10 19:11:48

+0

@ M4N ack,我沒有檢查「re-entrant」:) – Dave 2010-09-10 19:12:18

回答

16

是的,基於.NET中的Monitor的鎖是遞歸的並且被計數。

從文檔的Monitor.Enter

是合法的同一線程調用 輸入不止一次沒有它 阻塞;然而,在等待對象 的其他線程將被取消阻止之前,必須調用相同數量的退出調用 。

這是否是一件好事或不可達的辯論......

+0

「up for debate」鏈接轉到Monitor.Enter文檔。你能編輯你的答案並提供你想要的鏈接嗎? – 2010-09-10 19:11:06

+0

好的,這是有道理的。現在我應該用一個小應用程序來測試它,但是我認爲如果在lock(){}語句中引發異常並且未處理異常,ref計數仍然遞減? – Dave 2010-09-10 19:13:58

+0

@Dave遞減。 – eglasius 2010-09-10 19:31:53

4

是,Monitor支持遞歸,但因爲這種行爲從一個同步原語到另一個不同的,你應該知道。

例如,ReaderWriterLockSlim默認情況下不支持遞歸和此代碼段拋出異常:

public class MyClass 
{ 
    ReaderWriterLockSlim rw = new ReaderWriterLockSlim(); 
    //You should explicitly stated that you want to use recursion 
    ReaderWriterLockSlim rwWithRecursion = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion); 

    public void MethodA() 
    { 
     try { 
      rw.EnterReadLock(); 
      // do something 
      MethodB(); 
     } 
     finally { 
      rw.ExitReadLock(); 
     } 
    } 

    public void MethodB() 
    { 
     try { 
      rw.EnterReadLock(); //throws LockRecursionException 
     } 
     finally { 
      rw.ExitReadLock(); 
     } 
    } 
} 
+0

謝謝,我會記住這一點。我還沒有找到需要對於ReaderWriterLockSlim,但我之前已經閱讀過它,有一天它可能會派上用場,所以希望我會記住你的建議。:) – Dave 2010-09-10 21:09:46