看这么几句解释(英文原帖):

private static void ConcurrentDictionary()
{
var dict = new ConcurrentDictionary<int, string>();
ThreadPool.QueueUserWorkItem(LongGetOrAdd(dict, ));
ThreadPool.QueueUserWorkItem(LongGetOrAdd(dict, ));
} private static WaitCallback LongGetOrAdd(ConcurrentDictionary<int, string> dict, int index)
{
return o => dict.GetOrAdd(index,i =>
{
Console.WriteLine("Adding!");
Thread.SpinWait(); return i.ToString();
}
);
}

1) threadA calls GetOrAdd, finds no item and creates a new item to Add by invoking the valueFactory delegate.

线程A调用GetOrAdd,发现数据不存在并创建了一条新数据,准备调用委托方法添加数据

2) threadB calls GetOrAdd concurrently, its valueFactory delegate is invoked and it arrives at the internal lock before threadA, and so its new key-value pair is added to the dictionary.

线程B现在也在调用GetOrAdd方法,它的委托被调用了,比线程A先进入GetOrAdd内部的锁,因此它创建的键值对被添加到dict中了

3) threadA’s user delegate completes, and the thread arrives at the lock, but now sees that the item exists already

线A的委托执行完成了,并且也获得了GetOrAdd的锁,但是现在发现相关数据已经存在了

4) threadA performs a "Get", and returns the data th at was previously added by threadB.

线程A执行“Get”,返回之前被线程B添加的数据

不止这个英文原帖,好多国内的帖子都在说这个问题。

然而我觉得这并不是个问题,这最多是一个编程时需要注意的事项,微软的这个设计是合理的:ConcurrentDictionary没有理由也没有职责去把外部代码加锁,外部代码的同步应该由

外部控制。回头看看上面的解释,我们发现只不过是传递给ConcurrentDictionary的委托被执行了不止一次,但数据仍然只添加了一次,ConcurrentDictionary已经完全履行了自己的职责,而且MSDN也作了相关的说明(事实上,上面的四句英文也来自MSDN):

The user delegate that is passed to these methods is invoked outside of the dictionary's internal lock. (This is done to prevent unknown code from blocking all threads.)

传递进来的用户委托在字典内部锁的外面调用,这么做是为了防止阻塞所有相关线程,具体参考MSDN

都说ConcurrentDictionary<TKey, TValue>有陷阱的更多相关文章

  1. 线程安全集合 ConcurrentDictionary<TKey, TValue> 类

    ConcurrentDictionary<TKey, TValue> 类 [表示可由多个线程同时访问的键/值对的线程安全集合.] 支持 .NET Framework 4.0 及以上. 示例 ...

  2. C#字典 Dictionary<Tkey,Tvalue> 之线程安全问题 ConcurrentDictionary<Tkey,Tvalue> 多线程字典

    ConcurrentDictionary<Tkey,Tvalue>  Model #region 程序集 mscorlib, Version=4.0.0.0, Culture=neutra ...

  3. .net源码分析 - ConcurrentDictionary<TKey, TValue>

    List源码分析 Dictionary源码分析 ConcurrentDictionary源码分析 继上篇Dictionary源码分析,上篇讲过的在这里不会再重复 ConcurrentDictionar ...

  4. ConcurrentDictionary<TKey, TValue>的AddOrUpdate方法

    https://msdn.microsoft.com/zh-cn/library/ee378665(v=vs.110).aspx 此方法有一共有2个,现在只讨论其中一个 public TValue A ...

  5. c# 扩展方法奇思妙用基础篇五:Dictionary<TKey, TValue> 扩展

    Dictionary<TKey, TValue>类是常用的一个基础类,但用起来有时确不是很方便.本文逐一讨论,并使用扩展方法解决. 向字典中添加键和值 添加键和值使用 Add 方法,但很多 ...

  6. “线程安全的” Dictionary(TKey,TValue)

    这是一篇翻译,专门介绍Dictionary线程安全问题,原文网址如下 http://www.grumpydev.com/2010/02/25/thread-safe-dictionarytkeytva ...

  7. .net源码分析 – Dictionary<TKey, TValue>

    接上篇:.net源码分析 – List<T> Dictionary<TKey, TValue>源码地址:https://github.com/dotnet/corefx/blo ...

  8. .NET中Dictionary<TKey, TValue>浅析

    .NET中Dictionary<TKey, Tvalue>是非常常用的key-value的数据结构,也就是其实就是传说中的哈希表..NET中还有一个叫做Hashtable的类型,两个类型都 ...

  9. .net学习笔记----有序集合SortedList、SortedList<TKey,TValue>、SortedDictionary<TKey,TValue>

    无论是常用的List<T>.Hashtable还是ListDictionary<TKey,TValue>,在保存值的时候都是无序的,而今天要介绍的集合类SortedList和S ...

随机推荐

  1. 网页中"IE限制网页访问脚本或ActiveX控件"的提示问题的解决方法

    以前从来没有注意过"IE限制网页访问脚本或ActiveX控件"的提示问题,对于这个小细节问题,虽然感觉很别扭,但一直没考虑解决方法,今天才发现该问题可以轻松解决,以下做个小小记录. ...

  2. javaweb——总结

    day01XML上    1.XML的作用    2.XML的基本语法    3.DTD约束    4.DTD的基本语法(看懂DTD就ok)    5.XML的解析方式:原理    6.JAXP的DO ...

  3. 伪装隐藏Nginx,PHP版本号提升服务器安全性

    可能有时候我们看某些站点想知道别人在使用什么版本的web服务器之类的信息时,却发现并未显示版本号,甚至连WEB服务器都有变化,可以通过以下 方法来隐藏Nginx.PHP的版本号信息,来提升一定的安全性 ...

  4. configure: error: zlib library and headers are required

    configure: error: zlib library and headers are required (1)直接看是zlib没安装导致的,yum list |grep zlib* 看到的是全 ...

  5. Monitor All SQL Queries in MySQL (alias mysql profiler)

    video from youtube: http://www.youtube.com/watch?v=79NWqv3aPRI one blog post: Monitor All SQL Querie ...

  6. C++编写操作系统(1):基于 EFI 的 Bootloader

    很久以前就对操作系统很好奇,用了这么多年Windows,对他的运作机理也不是很清楚,所以一直想自己动手写一个,研究一下操作系统究竟是怎么实现的.后来在网上也找到过一些教程(比如:<自己动手写操作 ...

  7. Mac下无法推出硬盘

    Q:刚刚mac使用移动硬盘,使用后推出时弹出无法推出,提示:Finder正在使用中. 解决:打开#活动监视器#(找不到可以在spotlight中搜索),找到Finder应用,双击,强制退出后再启动Fi ...

  8. Unity3D连接真机调试教程,可抓断点

    源地址:http://www.unity蛮牛.com/thread-19586-1-1.html <ignore_js_op> 未标题-1.jpg (52.33 KB, 下载次数: 0) ...

  9. php nl2br() 函数

    nl2br() 函数在字符串中的每个新行 (\n) 之前插入 HTML 换行符 (<br />).

  10. Android MediaStore与Media.EXTERNAL_CONTENT_URI

    MediaStore这个类是Android系统提供的一个多媒体数据库,android中多媒体信息都可以从这里提取.这个MediaStore包括了多媒体数据库的所有信息,包括音频,视频和图像,andro ...