1 自身作为 Enumerable 的遍历

自身作为可遍历对象,键值对为元素进行遍历,是线程安全的,但不提供快照,遍历过程中集合产生变更会直接反馈至此次遍历过程中。但并不一定能够保障获取数据的过程中,映射出所有遍历过程中发生的变更,比如,已经遍历过的元素发生了变更或删除,便按已经遍历过的处理了,不会再次处置。

1.1 一起了解源码

GetEnumerator()

1.2 几点概念

  1. 线程安全:支持并发读写集合,能够保证集合的数据完整性和最终一致性。
  2. 快照(snapshot):集合快照时的数据内容和状态,原集合发生任何变更都不会体现在快照当中。如发生在遍历等操作前,则操作前集合中是哪些字段就是哪些,后续发生变更也不会反馈到此次操作当中。
  3. 集合变更:对于集合的增(添加元素)、删(移除元素)、改(变更元素属性)

2 做了 LINQ 操作之后进行遍历

由于没有做快照且没有自身 GetEnumerator 的线程安全处理,对集合做了 Where、OrderBy 等操作后,其对象变为 IEnumerable,此时遍历若集合内元素发生变更,则会报错。

2.1 解决办法

  1. 使用 ToArray() 或 Values 获取快照
  2. 再执行对应的 LINQ 操作。则操作针对的是快照,不会因集合发生变更而影响快照内容,从而产生线程安全问题

3 this[index]

  • getter:TryGetValue
  • setter:TryAddInternal:updateIfExists 为 true

4 TryAdd()

TryAddInternal:updateIfExists 为 false

5 TryUpdate()

  • 找得到键,尝试用新值更新旧值。
  • 找不到返回 false。

6 私有方法 TryAddInternal()

  • 找得到键,返回 false。同时若 updateIfExists 为 true 则用要添加的值更新原值。
  • 找不到则尝试添加并返回 true。

6.1 一起了解源码

private bool TryAddInternal(TKey key, TValue value, bool updateIfExists, bool acquireLock, out TValue resultingValue)

7 AddOrUpdate()

  1. TryGetValue,若键存在,TryUpdate。
  2. 若键不存在,TryAddInternal。
  3. 如果 try update 或 try add 没有成功返回 false,会反复尝试重新 get 再根据 get 的结果再次 try update 或 try add。

7.1 其所解决的多线程并发问题

  1. A、B 两个线程同时想向集合添加键相同,值不相同的元素。集合中没有该键。
  2. A、B 两者都没 get 到 key
  3. A 先进 add,添加成功,key 对应 A 的值。
  4. B 后进 add,try add 失败,重新尝试
  5. 重新尝试 B 的处理,B get 到 key,updateValueFactory 通过将 value 作为引用对象,将 B 所需更新到 value 中的内容,在原有 value 的基础上添加到 value 中,而不影响原有 value(不同于 this[index] 的强制赋值)。
  6. try update,key 更新 value,同时包含 A 和 B 的内容。

AddOrUpdate 通过重新尝试可以解决并发问题,属于线程安全中不仅保障数据最终一致性,还能够保障数据不丢失的并发处理。

7.2 一起了解源码

AddOrUpdate()

8 Values

通过加锁达到快照效果,遍历 Values 的话所遍历的是修改前的集合,遍历过程中集合发生的变更不会体现在此次遍历当中。由于是快照,无论直接遍历还是 Linq 操作后遍历都是线程安全的。

8.1 一起了解源码

GetValues()

9 ToArray()

通过加锁达到快照效果,遍历 ToArray 后的 KeyValuePair 数组的话所遍历的是修改前的集合,遍历过程中集合发生的变更不会体现在此次遍历当中。由于是快照,无论直接遍历还是 Linq 操作后遍历都是线程安全的。

9.1 一起了解源码

ToArray()

C# - ConcurrentDictionary 并发场景使用注意事项的更多相关文章

  1. ConcurrentDictionary并发字典知多少?

    背景 在上一篇文章你真的了解字典吗?一文中我介绍了Hash Function和字典的工作的基本原理. 有网友在文章底部评论,说我的Remove和Add方法没有考虑线程安全问题. https://doc ...

  2. 【性能诊断】六、并发场景的性能分析(windbg案例,大量的内部异常造成CPU飙升)

    在做产品的某个核心模块的性能优化时,发现压到100并发时应用服务器的CPU就飙升至90%以上,50并发以后TPS就基本定格在一个数值上.使用性能监视器收集应用服务器的数据,发现每秒的.NET CLR ...

  3. 高并发场景之RabbitMQ篇

    上次我们介绍了在单机.集群下高并发场景可以选择的一些方案,传送门:高并发场景之一般解决方案 但是也发现了一些问题,比如集群下使用ConcurrentQueue或加锁都不能解决问题,后来采用Redis队 ...

  4. Qunar机票技术部就有一个全年很关键的一个指标:搜索缓存命中率,当时已经做到了>99.7%。再往后,每提高0.1%,优化难度成指数级增长了。哪怕是千分之一,也直接影响用户体验,影响每天上万张机票的销售额。 在高并发场景下,提供了保证线程安全的对象、方法。比如经典的ConcurrentHashMap,它比起HashMap,有更小粒度的锁,并发读写性能更好。线程安全的StringBuilder取代S

    Qunar机票技术部就有一个全年很关键的一个指标:搜索缓存命中率,当时已经做到了>99.7%.再往后,每提高0.1%,优化难度成指数级增长了.哪怕是千分之一,也直接影响用户体验,影响每天上万张机 ...

  5. HashMap在并发场景下踩过的坑

    本文来自网易云社区 作者:张伟 关于HashMap在并发场景下的问题有很多人,很多公司遇到过!也很多人总结过,我们很多时候都认为这样都坑距离自己很远,自己一定不会掉入这样都坑.可是我们随时都有就遇到了 ...

  6. 【转】记录PHP、MySQL在高并发场景下产生的一次事故

    看了一篇网友日志,感觉工作中值得借鉴,原文如下: 事故描述 在一次项目中,上线了一新功能之后,陆陆续续的有客服向我们反应,有用户的个别道具数量高达42亿,但是当时一直没有到证据表示这是,确实存在,并且 ...

  7. 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...

  8. 高并发场景下System.currentTimeMillis()的性能问题的优化 以及SnowFlakeIdWorker高性能ID生成器

    package xxx; import java.sql.Timestamp; import java.util.concurrent.*; import java.util.concurrent.a ...

  9. 高并发场景之RabbitMQ

    高并发场景之RabbitMQ 上次我们介绍了在单机.集群下高并发场景可以选择的一些方案,传送门:高并发场景之一般解决方案 但是也发现了一些问题,比如集群下使用ConcurrentQueue或加锁都不能 ...

  10. HttpClient在高并发场景下的优化实战

    在项目中使用HttpClient可能是很普遍,尤其在当下微服务大火形势下,如果服务之间是http调用就少不了跟http客户端找交道.由于项目用户规模不同以及应用场景不同,很多时候可能不需要特别处理也. ...

随机推荐

  1. 天梯赛L1-027 出租

    一.问题描述 下面是新浪微博上曾经很火的一张图: 一时间网上一片求救声,急问这个怎么破.其实这段代码很简单,index数组就是arr数组的下标,index[0]=2 对应 arr[2]=1,index ...

  2. DFS手写排列

    DFS手写排列 虽然python中有自带的排列函数,但是在某些特殊情况需要手写排列.掌握了DFS手写排列对DFS的理解有一定的帮助. 1.手写排列(非字典序输出) 这种代码比较简单易懂,但是不是按照字 ...

  3. Awesome GPT 来了!

    大家好!我是韩老师. GPT, ChatGPT, OpenAI, LLM(大语言模型)等等技术的出现与应用,改变了许多的行业和人. 长期来看,类 GPT 的技术会对整个世界有着持续的改变. 我们几乎每 ...

  4. NLP入门1——李宏毅网课笔记

    近日因为项目需要,开始恶补预习NLP的相关知识.以前也看过两本相关书籍,但是都十分浅显.这次准备详细的学一下并记录. 李宏毅老师的网课是 Deep Learning for Human Languag ...

  5. 单窗算法的地表温度反演:谷歌地球引擎GEE代码

      本文介绍在GEE中基于Landsat遥感影像实现地表温度(LST)单窗算法反演的代码. 1 背景知识   基于遥感数据的地表温度(LST)反演目前得到了广泛的应用,尤其是面向大尺度.长时间范围的温 ...

  6. 关于聚合根,领域事件的那点事---深入浅出理解DDD

    作者:京东物流 赵勇萍 前言 最近有空会跟同事讨论DDD架构的实践落地的情况,但真实情况是,实际中对于领域驱动设计中的实体,值对象,聚合根,领域事件这些战术类的实践落地,每个人理解依然因人而异,大概率 ...

  7. .gitignore 文件语法介绍

    .gitignore 文件的作用 A gitignore file specifies intentionally untracked files that Git should ignore. Fi ...

  8. TCP/IP网络模型

    在网络模型中有分为7层模型(OSI模型)和5层模型和TCP/IP模型 OSI模型将应用层和表示层作为独立的两层,而TCP/IP模型将它们合并为一个应用层. 两种对比来说,TCP/IP模型更符合实际开发 ...

  9. 2023-02-14:魔物了占领若干据点,这些据点被若干条道路相连接, roads[i] = [x, y] 表示编号 x、y 的两个据点通过一条道路连接。 现在勇者要将按照以下原则将这些据点逐一夺回:

    2023-02-14:魔物了占领若干据点,这些据点被若干条道路相连接, roads[i] = [x, y] 表示编号 x.y 的两个据点通过一条道路连接. 现在勇者要将按照以下原则将这些据点逐一夺回: ...

  10. Netty(1)——NIO基础

    本篇主要介绍Java NIO的基本原理和主要组件 Netty是由JBOSS提供的Java开源网络应用程序框架,其底层是基于Java提供的NIO能力实现的.因此为了掌握Netty的底层原理,需要首先了解 ...