【问题标题】:Adding a new item in dictionary from multiple threads从多个线程在字典中添加新项目
【发布时间】:2017-02-07 17:47:49
【问题描述】:

我在从多个线程中使用静态字典时向静态字典添加新项时遇到问题。有什么想法我做错了吗? 初始化字典:

public static class Server
{
    public static volatile Dictionary<int, List<SomeClass>> Values;
}

尝试添加项目:

Server.Values.Add(someInt, new List<SomeClass> { elements});

【问题讨论】:

  • 是的,您使用的类型被记录为不是线程安全的,来自多个线程,没有任何保证安全的东西。
  • 我想我可能猜到了,但你为什么不告诉我们问题出在哪里而不是让我们猜测呢?
  • 错误是什么?
  • 这就是问题所在 - 工作室没有给出错误 - 它只是中断
  • 定义“中断”

标签: c# multithreading dictionary concurrency


【解决方案1】:

正如 Jon Skeet 所解释的,您使用的对象不能保证是线程安全的

尝试使用专为多线程并发场景设计的ConcurrentDictionary

public static class Server
{
    public static  ConcurrentDictionary<int, List<SomeClass>> Values =
                      new ConcurrentDictionary<int, List<SomeClass>>(); 
}

这里是怎么用的

bool added = Server.Values.TryAdd(someInt, new List<SomeClass> { elements});

【讨论】:

  • @TimSchmelter 做得很好,我忘了添加它。这是一个时间限制
  • 在这种情况下添加 = false 和 Server.Values = null。这就是我得到的大部分“错误”
  • 你必须先初始化它我更新了我的答案
【解决方案2】:

一般来说,在处理多个线程之间共享的资源时,您需要使用同步机制,例如lock(),以确保您的代码线程安全。创建一个通用对象用作锁:

private object _lock = new object();

然后你包围任何访问你的共享资源的代码,像这样:

lock(_lock)
{
    // perform operations on shared resource here.
}

请务必注意,您应该为每个共享资源使用不同的锁,而不是为所有资源使用一个锁。如果您将锁定对象与多个资源一起使用,您的代码可能会非常低效。如果一个线程获取了锁,所以它可以使用资源A,那么其他线程即使要访问与资源A无关的资源B,也必须等待锁释放。因此,最好有每个资源一个锁对象并命名您的锁对象,以便您知道它们应该与哪些资源一起使用。

对此的替代方法(如 BRAHIM Kamel 的回答所示)是为您的共享资源使用替代(如果可用),该共享资源已经嵌入了线程同步,例如 ConcurrentDictionary。尽管在您的情况下这可能不可行。

【讨论】:

  • 如果你有 concurrentDictionary,为什么要重新定义轮子:p
  • 这个值得一提,以防他不能改变类型+1
  • 我更喜欢一个变量ServerDictionaryLock,然后很清楚你用它锁定了什么。
  • @TimSchmelter -- 好吧,我尽量让它通用,但我明白你的意思。
  • @rory.ap:_lock 对象的问题在于人们以这种方式实现它,它建议每个类使用一个锁变量。这将锁定整个实例以及使用它的任何操作。
猜你喜欢
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
  • 2011-05-13
  • 2021-03-27
  • 2014-09-14
  • 2021-12-05
  • 1970-01-01
相关资源
最近更新 更多