2011-09-30 124 views
1

我接收在生產與消息的異常上Mutex.ReleaseMutex(「對象同步方法從碼非同步塊被稱爲」在下面的代碼稱爲:對象同步方法是從代碼)不同步塊

Mutex Mutex 
{ 
    get { return mutex ?? (mutex = new Mutex(false, mutexName)); } 
} 
[NonSerialized] 
Mutex mutex; 

public void Log(/*...*/) 
{ 
    Mutex.WaitOne(); 
    try 
    { 
     /*...*/ 
    } 
    finally 
    { 
     Mutex.ReleaseMutex(); 
    } 
} 

可能存在可以使用具有不同且相同mutextName的互斥體的保存進程。 而我仍然不確定那裏的例外情況如何發生。

+0

其實我懷疑它可能是因爲Mutex.WaitOne()和Mutex.ReleaseMutext()中使用不同的互斥體實例,因爲單個進程內部存在一些競態條件,儘管存在疑問。 –

+1

您的互斥體的創建不是線程安全的 - 對於初學者。您最終可能擁有多個互斥鎖。 – vcsjones

+1

是的,釋放呼叫是在額外的一個。 –

回答

7

此代碼:

Mutex Mutex 
{ 
    get { return mutex ?? (mutex = new Mutex(false, mutexName)); } 
} 

不是線程安全的,超過一個互斥體可能會產生。使用假裝時間,我們來看看這個例子:

 
Thread A  | Thread B 
------------------------------------- 
Enters 
Is Null? (yes) Enters 
Create Mutex  Is Null? (yes) <- Thread A hasn't assigned it yet. 
Assign mutex  Create Mutex 
Use Mutex  Assign mutex <- Oops! We just overwrote the mutex thread A created! 
Release Mutex <- Oops! We are trying to release the mutex Thread B created without owning it! 

希望插圖不是垃圾。

使用System.Lazy<T>類是一種執行延遲初始化的線程安全方式,如果您真的想用您的互斥鎖來執行此操作。

private Lazy<Mutex> _lazyMutex = new Lazy<Mutex>(() => new Mutex(false, "MyMutex")); 
Mutex Mutex 
{ 
    get { return _lazyMutex.Value; } 
} 

鑑於此,您爲什麼試圖懶惰地初始化您的Mutex?你怎麼處理它?

+0

處理保持對象時,配置互斥鎖。 –