什么是 ConcurrentDictionary?

ConcurrentDictionary<TKey, TValue> 是 .NET Framework 4.0+ 和 .NET Core/.NET 5+ 中引入的线程安全字典实现,位于 System.Collections.Concurrent 命名空间。它解决了多线程环境下操作字典时的同步问题,允许**多个线程同时读写字典**而无需显式加锁。

核心特性

  1. 线程安全:所有操作都是原子性的
  2. 高性能:使用细粒度锁(而非全局锁)
  3. 无锁读取:读操作通常不需要锁
  4. 原子方法:提供专门设计的线程安全方法

与普通 Dictionary 的对比

特性DictionaryConcurrentDictionary
线程安全❌ 需要手动加锁✅ 内置线程安全
读性能非常高(无锁读取)
写性能较高(细粒度锁)
并发支持需要同步机制原生支持并发
内存开销较低稍高(维护内部结构)

基本使用

// 创建实例
var concurrentDict = new ConcurrentDictionary<string, int>();// 添加元素(线程安全)
concurrentDict.TryAdd("task1", 0);
concurrentDict.TryAdd("task2", 0);// 更新元素(原子操作)
concurrentDict.AddOrUpdate("task1", key => 1,               // 添加时的工厂函数(key, oldValue) => oldValue + 1 // 更新时的函数
);// 安全获取值
if (concurrentDict.TryGetValue("task1", out int value))
{Console.WriteLine($"Task1 进度: {value}%");
}// 删除元素
concurrentDict.TryRemove("task2", out _);

关键方法详解

1. TryAdd()
bool success = concurrentDict.TryAdd("task3", 25);
// 成功添加返回 true,键已存在返回 false
2. TryUpdate()
int currentValue;
do {currentValue = concurrentDict["task1"];
} while (!concurrentDict.TryUpdate("task1", currentValue + 10, currentValue));
// 原子性更新:只有当前值等于 expectedValue 时才更新
3. AddOrUpdate()
// 添加或更新(原子操作)
int newValue = concurrentDict.AddOrUpdate("task1", key => 50,                // 添加时的工厂函数(key, oldValue) => oldValue + 10 // 更新时的函数
);
4. GetOrAdd()
// 获取或添加(原子操作)
int value = concurrentDict.GetOrAdd("task4", key => 0);
// 如果 task4 不存在,初始化为 0
5. TryRemove()
if (concurrentDict.TryRemove("task2", out int removedValue))
{Console.WriteLine($"已删除 task2,原值: {removedValue}");
}

在任务进度系统中的应用

进度存储服务实现
public class ConcurrentTaskProgressService
{private readonly ConcurrentDictionary<string, TaskProgress> _progressStore = new ConcurrentDictionary<string, TaskProgress>();public void UpdateProgress(string taskId, int completed, int total){_progressStore.AddOrUpdate(taskId,// 添加新任务id => new TaskProgress{TaskId = id,Completed = completed,Total = total,LastUpdated = DateTime.UtcNow},// 更新现有任务(id, existing) =>{existing.Completed = completed;existing.Total = total;existing.LastUpdated = DateTime.UtcNow;return existing;});}public TaskProgress GetProgress(string taskId){return _progressStore.TryGetValue(taskId, out var progress) ? progress : null;}
}public class TaskProgress
{public string TaskId { get; set; }public int Completed { get; set; }public int Total { get; set; }public DateTime LastUpdated { get; set; }public int Percentage => Total > 0 ? (Completed * 100) / Total : 0;
}

最佳实践

  1. 优先使用原子方法

    // ✅ 推荐
    dict.AddOrUpdate(key, 1, (k, v) => v + 1);// ❌ 避免(非原子操作)
    if (dict.ContainsKey(key)) {dict[key] = dict[key] + 1;
    }
    
  2. 处理工厂函数副作用

    // 工厂函数应简单无副作用
    var value = dict.GetOrAdd(key, k => {// 避免耗时操作return CalculateInitialValue(k);
    });
    
  3. 迭代时处理并发修改

    foreach (var pair in concurrentDict)
    {// 注意:迭代期间字典可能被修改Process(pair.Value);
    }
    
  4. 值类型注意事项

    // 值类型更新需特殊处理
    var dict = new ConcurrentDictionary<string, (int, DateTime)>();dict.AddOrUpdate("task", k => (0, DateTime.UtcNow),(k, v) => (v.Item1 + 1, DateTime.UtcNow)
    );
    

性能考量

  1. 读取密集型场景:性能接近无锁读取
  2. 写入密集型场景:比锁+Dictionary 性能高 2-3 倍
  3. 混合工作负载:在高并发下表现最佳

使用场景

  1. 缓存系统
  2. 实时监控/统计
  3. 并行计算中间结果
  4. 高并发计数器
  5. 任务调度系统(如所述进度监控)

总结

ConcurrentDictionary 是 .NET 中处理并发字典操作的首选方案,它:

  • 提供线程安全的原子操作
  • 比手动锁实现更高效
  • 简化多线程编程模型
  • 特别适合高频读写的场景

在任务进度监控系统中,使用 ConcurrentDictionary 可以安全高效地管理多个任务的进度状态,确保在高并发环境下数据的一致性和实时性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/92680.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92680.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/92680.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

集成电路学习:什么是URDF Parser统一机器人描述格式解析器

URDF Parser(URDF解析器)是ROS(Robot Operating System,机器人操作系统)中用于解析URDF(Unified Robot Description Format,统一机器人描述格式)文件的工具。URDF是一种基于XML(Extensible Markup Language,可扩展标记语言)规范的格式,用于描述机器人的结构、关节、…

老式大头显示器(CRT)和当前最高分辨率的LED显示器对比

老式 CRT&#xff08;阴极射线管&#xff09;和当前最顶尖的 LED&#xff08;包括 MicroLED / 高端 MiniLED / OLED&#xff09;显示器在画面清晰度极限相关的参数并列分析。1. 分辨率与像素密度指标老式 CRT&#xff08;PC/电视用&#xff09;顶级 LED 显示器&#xff08;2025…

北京JAVA基础面试30天打卡07

1. 缓存三大问题及解决方案问题场景后果常用解决方案缓存穿透请求的数据在缓存和数据库中都不存在&#xff08;恶意攻击或查询异常 ID&#xff09;每次请求都会打到数据库&#xff0c;导致 DB 压力骤增- 缓存空值&#xff08;短期缓存不存在的 key&#xff09;- 布隆过滤器&…

后量子密码学的迁移与安全保障:迎接量子时代的挑战

在当今数字化时代&#xff0c;信息安全无疑是保障个人隐私、企业运营和国家安全的基石。我们依赖密码学来保护敏感信息&#xff0c;从在线银行交易到机密军事通信&#xff0c;从医疗记录的存储到云计算中的数据传输&#xff0c;传统密码学为我们构筑起一道抵御恶意攻击的防线。…

Android 获取 UserAgent (UA) 的三种方式深度解析:差异、风险与最佳实践

引言 在 Android 开发中&#xff0c;获取 UserAgent (UA) 字符串是常见需求&#xff0c;尤其涉及网络请求和 WebView 交互时。开发者通常使用三种方式获取 UA&#xff1a; new WebView(context).getSettings().getUserAgentString()WebSettings.getDefaultUserAgent(context)…

Apache IoTDB 全场景部署:跨「端-边-云」的时序数据库 DB+AI 实战

时序数据正成为现代工业物联网的核心资产,从设备传感器到业务分析,数据需跨越端、边、云多个层级。本文将深入探讨 **Apache IoTDB** 如何实现全场景统一时序数据管理,并融合AI能力实现智能决策。 --- ### 一、为什么需要「端-边-云」协同? 在工业物联网场景中: - **端侧…

某地渣库边坡自动化监测服务项目

1. 项目简介该矿山主要从事稀有金属钽、铌及合金等的研发、生产、销售和进出口业务。具有科学的管理理念、精良的工艺装备、先进的技术水平、高素质的员工队伍等综合优势&#xff0c;已形成钽、铌金属及其合金材料等主要产业格局。公司产品被广泛应用于电子、通讯、航空、航天、…

redis(2)-java客户端使用(IDEA基于springboot)

一、准备工作首先确保&#xff1a;Linux 服务器上已安装并启动 Redis 服务Redis 已配置允许远程连接&#xff08;修改 redis.conf 文件&#xff09;开发环境&#xff08;IDEA&#xff09;已准备好二、Spring Boot 项目配置 Redis1. 添加依赖在pom.xml中添加 Redis 相关依赖&…

解决 vscode 编辑 markdown 文件时退格键/backspace 删除卡顿问题

文章目录发现问题解决问题发现问题 使用 vscode 编辑 markdown 时&#xff0c;发现有时按下退格键 backspace 后等待很久才会生效&#xff0c;卡顿明显 解决问题 从界面左下角的设置图标&#xff0c;打开 vscode 的键盘快捷键设置页面 Keyboard Shortcuts 搜索 backspace 按…

绿巨人VS Code多开项目单独管理每个项目单独使用一个不限制的augment

绿巨人VS Code多开项目单独管理每个项目单独使用一个不限制的augment 绿巨人VS前言 在AI辅助编程时代&#xff0c;Augment Code作为一款强大的代码助手工具&#xff0c;为开发者提供了智能代码补全、代码生成等功能。然而&#xff0c;免费版本的使用限制&#xff08;通常为每月…

Java 之抽象类和接口

一 、抽象类 1.1 、什么是抽象类&#xff1f; 就是当一个类不能描述具体的对象时&#xff0c;那么这个类就可以写成抽象类。比如说 Animal &#xff0c;我们知道 Animal 不能非常清楚的描述一个具体的动物&#xff0c;所以可以把 Animal 写成抽象类。还有就是我们知道父类中的方…

【运维进阶】WEB 服务器

WEB 服务器 WEB 服务器简介 Web 服务器&#xff08;Web Server&#xff09;是指一种接收客户端&#xff08;如浏览器&#xff09;发送的 HTTP 请求&#xff0c;并返回网页内容或资源的程序或设备。它是万维网&#xff08;WWW&#xff09;的核心组成部分。 Web 服务器的主要功能…

LLM(大语言模型)的“幻觉”本质原因

LLM(大语言模型)的“幻觉”本质原因 LLM(大语言模型)的“幻觉”(生成与事实不符但模型自信输出的内容)本质上是其作为概率统计模型的底层机制与训练、推理过程中多重限制共同作用的结果。从模型内部逻辑、训练机制到推理环节 一、底层机制:基于“统计关联”而非“真实…

java基础(六)jvm

1. JVM内存的五大核心区域 一个帮手想象JVM运行程序时&#xff0c;需要划分不同区域干不同的事。主要分为这五大块&#xff0c;外加一个特殊帮手&#xff1a;1.1 程序计数器 (Program Counter Register) - 你的“任务进度条”干啥的&#xff1a; 专门记录当前线程执行代码执行…

计算机网络:什么是AD域

什么是AD域? AD域(Active Directory Domain)是微软基于Active Directory(活动目录) 技术构建的网络管理架构,用于集中管理网络中的用户、计算机、设备、权限等资源。它是企业级网络环境中实现身份认证、资源共享和安全控制的核心组件。 AD域的核心功能与作用 集中化身份…

虚幻基础:场景位置相对位置

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录绝对坐标&#xff1a;绝对坐标不会改变绝对坐标绝对方向x&#xff1a;世界的前y&#xff1a;世界的右z&#xff1a;世界的上相对坐标&#xff1a;坐标系的原点和方向会基于父组件 变换相对坐标相对方向&#xff1a;改…

【代码随想录day 16】 力扣 106.从中序与后序遍历序列构造二叉树

视频讲解&#xff1a;https://www.bilibili.com/video/BV1vW4y1i7dn/?vd_sourcea935eaede74a204ec74fd041b917810c 文档讲解&#xff1a;https://programmercarl.com/0106.%E4%BB%8E%E4%B8%AD%E5%BA%8F%E4%B8%8E%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86%E5%BA%8F%E5%88%97%E6%9E…

vue+flask大模型写诗诗词推荐与可视化系统

文章结尾部分有CSDN官方提供的学长 联系方式名片文章结尾部分有CSDN官方提供的学长 联系方式名片关注B站&#xff0c;有好处&#xff01;编号&#xff1a; F061 大模型诗词推荐与可视化系统 在传统文化数字化的浪潮下&#xff0c;我开发了这款诗歌问答大数据平台&#xff0c;旨…

Apache Ignite 核心组件:GridClosureProcessor解析

这是一个 Apache Ignite 中非常核心的组件 —— GridClosureProcessor&#xff0c;它是 分布式闭包&#xff08;Closure&#xff09;执行的调度中枢&#xff0c;负责在集群节点上异步执行用户提交的任务&#xff08;如 Runnable、Closure&#xff09;。 我们来逐层深入理解它的…

for循环详解与实战技巧

目录 一、for循环语法 二、for循环执行流程 流程图表示&#xff1a; 三、for循环实践示例 示例&#xff1a;在屏幕上打印1~10的值 四、while循环与for循环对比 for循环和while循环都包含三个关键部分&#xff1a; 两者的主要区别在于代码组织方式&#xff1a; 五、练习…