2014-05-19 61 views
2

所以爲了對每個線程的程序運行我成立了一個上下文一個單獨的上下文 - 主題映射類如下是否有可能爲有管理的線程有自己的競爭條件

 public class ContextMap : IContextMap 
{ 
    private static IContextMap _contextMap; 
    private Dictionary<int, IArbContext2> ContextDict; 
    private static string DbName; 
    private ContextMap() 
    { 
     if (string.IsNullOrWhiteSpace(DbName)) 
      throw new InvalidOperationException("Setup must be called before accessing ContextMap"); 
     ContextDict = new Dictionary<int, IArbContext2>(); 
    } 

    protected internal static void Setup(IContextMap map) 
    { 
     _contextMap = map; 
    } 

    public static void Setup(string dbName) 
    { 
     DbName = dbName; 
    } 

    public static IContextMap GetInstance() 
    { 
     return _contextMap ?? (_contextMap = new ContextMap()); 
    } 


    public IArbContext2 GetOrCreateContext() 
    { 
     var threadId = Thread.CurrentThread.ManagedThreadId; 
     if(!ContextDict.ContainsKey(threadId)) 
      ContextDict.Add(threadId,new ArbContext(DbName)); 
     return ContextDict[threadId]; 
    } 

    public void DestroyContext() 
    { 
     if (ContextDict.ContainsKey(Thread.CurrentThread.ManagedThreadId)) 
      ContextDict.Remove(Thread.CurrentThread.ManagedThreadId); 
    } 

不知何故,代碼是(很少但仍然發生)在GetOrCreateContext方法中拋出keynotfound異常。是否有可能將線程轉移到單獨的動作(例如,監督線程迫使它執行另一個動作,在線程檢查Dict是否有鍵但尚未返回之前調用DestroyContext),然後恢復它離開的地方。我從來沒有特意這樣做,但我不明白任何其他原因如何引發此錯誤。

謝謝。

+0

你是不是一個展示如何調用'GetOrCreateContext'和'DestroyContext'。可能它從多線程調用沒有適當的同步...附註:從我可以看到你正在重新實現線程本地存儲([SO Q:ThreadLocal](http://stackoverflow.com/questions/2158981/does- c-sharp-have-a-threadlocal-analog-for-data-members-to-the-threadstatic)作爲起點)。 –

+0

這難道不使DIF如可以在代碼中看到上下文被創建和存儲由線程ID,它不可能對任何線程影響任何情況下,它不擁有 – Alex

+0

如果沒有一個以上的線程參與你'重新說話是不可能的 –

回答

3

這裏的問題是,Dictionary不是線程安全的。當多個線程嘗試訪問它時,即使它們都使用唯一鍵,也會出現意外的行爲,因爲創建或刪除鍵/值對不是原子操作。

最簡單的解決將是使用它的地方ConcurrentDictionaryContextDict

+1

+1。請注意,實際的問題是OP沒有看到多線程訪問'Dictionary'的問題。 –

+0

謝謝你的答案。我認爲只要有訪問控制,我就需要採取任何預防措施 - 特別是因爲線程之間沒有任何競爭條件。我會執行此操作,看看問題是否會停止。 – Alex

+0

@亞歷山大右。你可以找到這方面的信息,例如這裏:http://social.msdn.microsoft。com/Forums/vstudio/en-US/021a235b-b930-460a-b093-72acbacbb97d/generic-dictionary-operations-and-threadingis-read-and-write-lock-necessary-if-not-enumerating?forum = netfxbcl There's可能大量的文章。各種各樣的優化等等都意味着它不僅僅是確保按鍵不同而是簡單 –

0

回答你的問題的文字,試圖解決您的問題。 (@BenAaronsom已經這樣做了。)

不,你有一個「競態條件」時,一些計算的結果取決於兩個或多個線程訪問相同的變量的順序。如果比賽中只有一個線程在運行,那麼不管你運行多少次,同一個線程總是會贏。如果單線程程序給出了非確定性答案,那麼無論問題是什麼,它都不是競爭條件。

+0

純粹的理論......但是不能這樣做,如果你正在使用回調系統 – Alex

+2

@Alex,有一些單線程程序產生非確定性結果的方法,並且有很多方法可以實現產生一個意想不到的結果,但我不會調用他們中的任何一個_r​​ace_條件。除非有兩個或更多賽車手(線程),並且結果/行爲/最終狀態取決於哪一位贏得比賽,否則我不會將其稱爲「競賽條件」。 –