2014-05-19 37 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_条件。除非有两个或更多赛车手(线程),并且结果/行为/最终状态取决于哪一位赢得比赛,否则我不会将其称为“竞赛条件”。 –