2010-04-30 22 views
3

我想知道以下哪個是使用Mutex(或Semaphores或ReadWriteLockSlims等)時的建議模式。應該mutex.WaitOne()之內或之前的try/finally塊

初始鎖定是否應該在try語句內部或外部發生?它不重要嗎?

_mutex.WaitOne() 
try 
{ 
// critical code 
} 
finally 
{ 
    _mutex.ReleaseMutex(); 
} 

try 
{ 
    _mutex.WaitOne() 
// critical code 
} 
finally 
{ 
    _mutex.ReleaseMutex(); 
} 

回答

0

也許是不同的。看看進入埃裏克這些帖子:

簡而言之: 試想有發生在mutex.WaitOne()try語句之間異常。您將不用撥打_mutex.ReleaseMutex()就可以離開這段代碼。

因此,請確保您的第二段代碼能夠按預期工作。

+0

但是你現在不叫ReleaseMutex而另一個線程可能是它裏面允許第二個線程進入?即線程A調用WaitOne並進入互斥體 - >線程B調用WaitOne和塊 - >線程C崩潰並調用ReleaseMutex - >線程B與線程A一起輸入互斥體。 – 2014-11-13 11:51:31

2

這些可能不同的唯一方法是如果在WaitOne之後,但在例子1中嘗試啓動之前,或在嘗試啓動之後但在例子2中的WaitOne之前發生異常。在第一種情況下,互斥體將不會被釋放而在第二種情況下,即使沒有待處理的等待,也可能嘗試釋放。例外情況必須是嚴重的事情,例如ThreadAbortException,因爲它發生在任何地方。但是,如果互斥量包含在使用塊中,則兩者都不成問題。

編輯:在閱讀Eric關於奧利弗鏈接到的這個主題的帖子後,我認爲即使是使用塊,情況也不是很完美,簡單地跟你的第二個版本一樣,奧利弗建議你是最好的選擇。

+0

在一個使用塊中如何使用互斥體?如果它僅存在於使用塊的生命週期中,則其他線程無法訪問它。 – chillitom 2010-04-30 10:23:08

+0

在字段中持有對互斥鎖的引用的任何對象本身都應該是一次性的,並將任何配置傳播給互斥鎖。如果鏈是完整的,將頂級對象(在你所處理的生命週期級別)放置在一個dispose塊中將確保互斥體被處置。如果互斥體生命週期==應用程序的生命週期那麼是什麼問題?它將在應用程序存在時發佈。 – 2010-04-30 10:30:14

+0

new Mutex()和_mutex.Dispose()與_mutex.WaitOne()和_mutex.ReleaseMutex()不同。'using'語句將處理Mutex對象的生命週期,但不處理鎖定狀態在互斥體的生命週期中發生異常之後。 – chillitom 2010-04-30 10:35:14

0

如果您不使用互斥鎖進行跨進程同步。

見這個問題的答案C# - Locking issues with Mutex

那麼這將是更安全:

private static object _syncLock = new object(); 

public void RunCriticalCode() 
{ 
    lock (_syncLock) 
    { 
     // critical code 
    } 
} 
+0

謝謝Jens,這是一個很好的觀點,需要牢記。我想我在這裏概括了所有的鎖,但是我在代碼中使用了ReadWriteLockSlim。雖然答案很好。 – chillitom 2010-04-30 10:49:20

+0

@chillitom,好的,回答你的原始問題,我將不得不同意奧利弗的答案。 – 2010-04-30 11:01:09

相關問題