2009-08-19 119 views
45

有什麼方法可以確定一個對象是否被鎖定在C#中?我有一個難以置信的地位,通過設計,我正在從一個班級裏的一個隊列裏讀書,我需要將這些內容轉儲到班級中的一個集合中。但是該集合也可以從類外部的接口讀取/寫入。所以顯然可能會出現集合正在寫入的情況,同時我想寫入該集合。有沒有辦法檢測對象是否被鎖定?

我可以對它進行編程,比如使用委託,但它會很難看。

+0

是的, 謝謝大家。這幾乎證實了我的想法。 – 2009-08-19 15:14:08

回答

40

您可以始終使用Monitor class上的靜態TryEnter method呼叫等待值爲0。如果它被鎖定,則該呼叫將返回錯誤。

但是,這裏的問題是,您需要確保您嘗試同步訪問權限的列表被鎖定在自身上,以同步訪問權限。

通常不好的做法是使用正在同步訪問的對象作爲鎖定對象(暴露對象的內部細節太多)。

請記住,鎖可以在其他任何東西上,所以只要在列表中調用它就沒有意義,除非您確定該列表是被鎖定的。

10

Monitor.TryEnter如果對象沒有被鎖定就會成功,如果此時對象被鎖定,將返回false。但是請注意,這裏存在隱式競爭:此方法返回的實例,對象可能不再被鎖定。

6

當前您可以調用Monitor.TryEnter來檢查對象是否被鎖定。

在.NET CLR 4.0團隊將添加 「鎖定檢查API」

這裏是Rick Byers文章報價:

鎖檢查
我們增加了一些簡單的API到ICorDebug,它允許您探索托管鎖(監視器)。例如,如果線程被阻塞等待鎖定,您可以找到其他線程當前正在鎖定的鎖定(以及是否有超時)。

所以,用這個API,你將能夠檢查:
1)什麼對象是持有鎖?
2)誰在等待?

希望這會有所幫助。

+0

有趣。 鮑勃。 – 2009-08-19 15:03:30

7

我不知道如果一個靜態調用TryEnter的時間爲0將保證鎖定將不被獲取,如果它是可用的。我確實在調試模式下,測試溶液中的同步變量使用以下被鎖定:

#if DEBUG 
// Make sure we're inside a lock of the SyncRoot by trying to lock it. 
// If we're able to lock it, that means that it wasn't locked in the first 
// place. Afterwards, we release the lock if we had obtained it. 
bool acquired = false; 
try 
{ 
    acquired = Monitor.TryEnter(SyncRoot); 
} 
finally 
{ 
    if (acquired) 
    { 
     Monitor.Exit(SyncRoot); 
    } 
} 
Debug.Assert(acquired == false, "The SyncRoot is not locked."); 
#endif 
+2

變量'isNotLocked'被命名得相當糟糕。如果'isNotLocked'爲真,則解鎖 - 雖然從技術上講它是正確的,因爲當鎖成功獲取時,isNotLocked將成立,上面的代碼真的不好閱讀。如果有其他人必須在此工作,他將有一個WTF時刻。 – ChrisWue 2013-10-20 20:12:01

+2

如果運行的線程是擁有該鎖的線程,則不起作用。它會說鎖是免費的,但事實並非如此。 – 2014-09-19 17:34:42

相關問題