首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ConcurrentDictionary中的更新列表

ConcurrentDictionary中的更新列表
EN

Stack Overflow用户
提问于 2017-01-11 13:23:49
回答 7查看 9.1K关注 0票数 9

因此,我的ConcurrentDictionary中有一个ConcurrentDictionary值。

代码语言:javascript
复制
ConcurrentDictionary<int, IList<string>> list1 = new ConcurrentDictionary<int, IList<string>>;

为了更新列表中的值,我执行以下操作:

代码语言:javascript
复制
if (list1.ContainsKey[key])
{
  IList<string> templist;
  list1.TryGetValue(key, out templist);
  templist.Add("helloworld");
}

但是,向templist添加字符串会更新ConcurrentDictionary吗?如果是的话,更新线程是否安全,这样就不会发生数据损坏?

或者是否有更好的方法来更新或创建ConcurrentDictionary中的列表

编辑

如果我使用的是ConcurrentBag而不是列表,我将如何实现这一点?更具体地说,我如何更新它?ConcurrentDictionary的TryUpdate方法感觉有点过火了。

ConcurrentBag.Add是否在线程安全的mannar中更新ConcurrentDictionary?

代码语言:javascript
复制
ConcurrentDictionary<int, ConcurrentBag<string>> list1 = new ConcurrentDictionary<int, ConcurrentBag<string>>
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2017-01-11 13:31:42

首先,不需要做ContainsKey()TryGetValue()

你应该这么做:

代码语言:javascript
复制
IList<string> templist;

if (list1.TryGetValue(key, out templist))
    templist.Add("helloworld");

实际上,编写的代码有一个争用条件。

在调用ContainsKey()TryGetValue()的一个线程之间,可能有不同的线程使用该键删除了项。然后TryGetValue()将返回tempList为null,然后在调用tempList.Add()时将得到一个空引用异常。

其次,是的:这里还有另一个可能的线程问题。您不知道字典中存储的IList<string>是线程安全。

因此,不能保证调用tempList.Add()是安全的。

您可以使用ConcurrentQueue<string>而不是IList<string>。这可能是最可靠的解决方案。

注意,仅仅锁定对IList<string>的访问是不够的。

这是不好的:

代码语言:javascript
复制
if (list1.TryGetValue(key, out templist))
{
    lock (locker)
    {
        templist.Add("helloworld");
    }
}

除非您在任何地方都使用相同的锁,否则可以访问IList。这并不容易实现,因此最好要么使用ConcurrentQueue<>,要么向该类添加锁定,然后更改体系结构,这样就不会有其他线程访问底层IList。

票数 7
EN

Stack Overflow用户

发布于 2017-01-11 13:29:32

可以说,线程安全字典上的操作按键是线程安全的.因此,只要您只从一个线程访问您的值(在本例中是一个IList<T>),您就可以继续了。

ConcurrentDictionary执行而不是,同时阻止两个线程访问一个键下面的值。

票数 4
EN

Stack Overflow用户

发布于 2017-01-11 13:32:21

可以使用ConcurrentDictionary.AddOrUpdate方法以线程安全的方式将项添加到列表中。它更简单,应该工作得很好。

代码语言:javascript
复制
var list1 = new ConcurrentDictionary<int, IList<string>>();
list1.AddOrUpdate(key, 
      new List<string>() { "test" }, (k, l) => { l.Add("test"); return l;});

UPD

根据文档资料来源,传递给AddOrUpdate方法的工厂将在锁定范围外运行,因此在工厂委托中调用List方法是不安全的。

见本答复下的评论。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41592129

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档