托管线程是否可能与自身具有竞争条件

时间:2014-05-19 16:37:41

标签: c# multithreading entity-framework

因此,为了为程序运行的每个线程提供单独的上下文,我设置了一个Context-Thread映射类,如下所示

      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)然后恢复它停止了。我从来没有专门这样做,但我无法理解如何抛出这个错误。

谢谢。

2 个答案:

答案 0 :(得分:3)

这里的问题是Dictionary不是线程安全的。当多个线程尝试访问它时可能会出现意外行为,即使它们都使用唯一键,因为创建或删除键/值对不是原子操作。

最简单的解决方法是在ConcurrentDictionary

的位置使用ContextDict

答案 1 :(得分:0)

回答您的文字问题, NOT 尝试解决您的问题。 (@BenAaronsom已经做到了。)

否:你有一个&#34;竞争条件&#34;当某些计算的结果取决于两个或多个线程访问同一变量的顺序时。如果在竞赛中只有一个线程运行,那么无论你运行多少次,同一个线程总是会赢。如果单线程程序给出了非确定性的答案,那么无论问题是什么,它都不是竞争条件。