2014-01-21 120 views
1

我有一個相當簡單的情況,兩個線程與相同的數據結構進行交互。線程託管在他們自己的責任類中。比方說,這些都是阿爾方階級和階級Belzebub:C#互斥參考

class Alfons { 
    public Mutex listMutex = new Mutex(); 

    private void ProcessListInfo() 
    { 
     listMutex.WaitOne(); 

     // 
     // ... Process multi-access list stuff ... 
     // 

     listMutex.ReleaseMutex(); 
    } 
} 

class Belzebub { 
    private Alfons mCachedAlfonsReference; 

    private void ProcessListInfoDifferently() 
    { 
     mCachedAlfonsReference.listMutex.WaitOne(); 

     // 
     // ... Process multi-access list stuff in a different fashion ... 
     // 

     mCachedAlfonsReference.listMutex.ReleaseMutex(); 
    } 
} 

我的問題是,是否引用一個互斥這樣可以創建一個併發的問題或者是否建議的做法這樣做。有沒有更好的方式來做到這一點,例如,我應該緩存互斥參考,而不是通過參考訪問它。

+0

是的!非常感謝你!事實上,我想把你們都當作答案(dcastro&acarlon)。我結束了對我的數據類型進行一些重組感謝:) – Muhwu

+0

很高興幫助 - dcastro是第一個,這麼公平。 – acarlon

回答

2

將不會有併發問題 - 該互斥量是假設被共享。按照Mutex MSDN docs

此類型是線程安全的。

但是,我會說數據結構本身應該同步來自不同線程的訪問。如果數據結構不支持(例如,使用SyncRoot),則封裝它並添加該功能。

出於好奇:你使用哪種數據結構?您可以考慮使用System.Collections.Concurrent集合中的一個來獲得無鎖/精細鎖定解決方案。另外,不會使用lock keyword更簡單,而且對於您的情況不太容易出錯。

1

我看不出緩存互斥體引用會有什麼區別,無論哪種方式您仍然通過引用訪問同一個對象,並且如果您不這樣做,那麼它會破壞互斥體的一點。

2

一般來說,由於鎖定可能會非常棘手,並且死鎖會停止所有樂趣,因此我嘗試減少與互斥鎖有關的代碼,而不是傳遞它。否則,找出哪條路徑導致鎖定可能會讓人頭疼。

這可能是更好的一類,然後封裝的資源和線程的關鍵操作:

Lock(this) 
{ 
} 

或者看看是否存在由dcastro提出了一個線程安全的版本。

除此之外,要非常小心,有WaitOne()ReleaseMutex()否則其他線程之間的不歸路(扔,等)將被無限期鎖定 - lockfinallyReleaseMutex在這方面更安全。正如卡斯特羅在評論中指出的那樣,它可能是另一個引發例外的圖書館。

最後,我假設它是ProcessListInfo()和ProcessListInfoDifferently()中受保護的資源。如果這些資源是受保護的兩種不同資源,那麼您已經擴大了不必要的線程爭用的可能性。

+0

+1,互斥量應該在'finally'塊中釋放,以防止可能的異常。即使你自己的代碼沒有故意拋出一個,但要注意的是像'ThreadAbortException'這樣的異常仍然可以發生。 – dcastro

+0

@dcastro - 同意。 – acarlon