都说ConcurrentDictionary<TKey, TValue>有陷阱
看这么几句解释(英文原帖):
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>有陷阱的更多相关文章
- 线程安全集合 ConcurrentDictionary<TKey, TValue> 类
ConcurrentDictionary<TKey, TValue> 类 [表示可由多个线程同时访问的键/值对的线程安全集合.] 支持 .NET Framework 4.0 及以上. 示例 ...
- C#字典 Dictionary<Tkey,Tvalue> 之线程安全问题 ConcurrentDictionary<Tkey,Tvalue> 多线程字典
ConcurrentDictionary<Tkey,Tvalue> Model #region 程序集 mscorlib, Version=4.0.0.0, Culture=neutra ...
- .net源码分析 - ConcurrentDictionary<TKey, TValue>
List源码分析 Dictionary源码分析 ConcurrentDictionary源码分析 继上篇Dictionary源码分析,上篇讲过的在这里不会再重复 ConcurrentDictionar ...
- ConcurrentDictionary<TKey, TValue>的AddOrUpdate方法
https://msdn.microsoft.com/zh-cn/library/ee378665(v=vs.110).aspx 此方法有一共有2个,现在只讨论其中一个 public TValue A ...
- c# 扩展方法奇思妙用基础篇五:Dictionary<TKey, TValue> 扩展
Dictionary<TKey, TValue>类是常用的一个基础类,但用起来有时确不是很方便.本文逐一讨论,并使用扩展方法解决. 向字典中添加键和值 添加键和值使用 Add 方法,但很多 ...
- “线程安全的” Dictionary(TKey,TValue)
这是一篇翻译,专门介绍Dictionary线程安全问题,原文网址如下 http://www.grumpydev.com/2010/02/25/thread-safe-dictionarytkeytva ...
- .net源码分析 – Dictionary<TKey, TValue>
接上篇:.net源码分析 – List<T> Dictionary<TKey, TValue>源码地址:https://github.com/dotnet/corefx/blo ...
- .NET中Dictionary<TKey, TValue>浅析
.NET中Dictionary<TKey, Tvalue>是非常常用的key-value的数据结构,也就是其实就是传说中的哈希表..NET中还有一个叫做Hashtable的类型,两个类型都 ...
- .net学习笔记----有序集合SortedList、SortedList<TKey,TValue>、SortedDictionary<TKey,TValue>
无论是常用的List<T>.Hashtable还是ListDictionary<TKey,TValue>,在保存值的时候都是无序的,而今天要介绍的集合类SortedList和S ...
随机推荐
- App开发中甲乙方冲突会闹出啥后果?H5 APP 开发可以改变现状吗
随着各种应用的全面App化,因App而起的合作纠纷也日益增多,其中不乏最终对簿公堂的情形.WeX5(html5开发工具)为您汇总了三个典型的真实案例,方便您体会甲乙方冲突情景. 在围观别人争吵之余,您 ...
- PHP中使用cURL
1.cURL介绍 cURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP.FTP.TELNET等.最爽的是,PHP也支持 cURL 库.本文将介绍 cURL 的一些高级特性 ...
- PHP字符
匹配查找 strstr strpos 通常用在表单验证里面可以用到 substr 正值表达式匹配 preg_mathc(), preg)mathc_all() , preg_grep() 编码格式的转 ...
- 《C和指针》读书笔记——第二章 基本概念
1.编译过程: source code→Compiler→Object code→Linker←Lib ↓ Exe 2.经过初始化的静态变量(static)在程序执行前能获得他们的值. 3.绝大多数环 ...
- About building ant & install ant on centos7 {ant source code 1.94}
hamcrest-junit-2.0.0.0.jar java-hamcrest-2.0.0.0.jar copy to ant-sourceCodeDir/lib/o ...
- leetcode解题—Longest Palindromic Substring
题目: Given a string S, find the longest palindromic substring in S. You may assume that the maximum l ...
- 查看 usb info
mount -t usbfs /proc/bus/usb /proc/bus/usb cat /proc/bus/usb/devices
- js pix
window.onload = function () { var img = new Image(); img.src = '1.gif'; var ctx = document.querySele ...
- 在Unity中高效工作(下)
原地址:http://www.unity蛮牛.com/thread-20005-1-1.html Tips for Creating Better Games and Working More Eff ...
- 编码问题 关于hibernate jdbc数据库连接在xml配置与在properties文件配置的差异
在properties中,&字符不需要转义,因此在连接数据库的时候使用编码的地方直接使用&即可: driverClass=com.mysql.jdbc.Driver jdbcUrl=j ...