托管线程是否可能与自己有竞争条件?

本文关键字:自己 竞争 条件 线程 是否 | 更新日期: 2023-09-27 18:04:17

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

      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异常。一个线程是否有可能被转移到一个单独的动作(例如,监督线程强制它做另一个动作,导致线程在检查字典是否有键后调用DestroyContext,但在它返回它之前),然后在它离开的地方恢复。我从来没有特别这样做过,但是我不明白为什么会抛出这个错误。

谢谢。

托管线程是否可能与自己有竞争条件?

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

最简单的修复方法是使用ConcurrentDictionary来代替ContextDict

回答你的字面问题,而不是试图解决你的问题。(@BenAaronsom已经这么做了)

No:当某些计算的结果取决于两个或多个线程访问同一变量的顺序时,就会出现"竞争条件"。如果赛跑中只有一个线程在运行,那么无论运行多少次,同一个线程总是会获胜。如果单线程程序给出了一个不确定的答案,那么无论问题是什么,它都不是竞争条件。