当前位置: 首页 > news >正文

C# Dictionary 线程安全指南:多线程下操作 Dictionary<string, DateTime> 的加锁策略

在讲述这个之前,我们先要弄清楚

为什么需要加锁

竞态条件示例

// 以下操作在多线程中都需要保护:
Dictionary<string, DateTime> dict = new Dictionary<string, DateTime>();// 线程A
if (!dict.ContainsKey("ip1"))  // 检查不存在// 此时线程B也检查同一个key,也不存在// 线程A
dict.Add("ip1", time);  // 成功添加// 线程B
dict.Add("ip1", time);  // 异常!键已存在

在C#中,当你在操作Dictionary<string, DateTime>这样的集合时,是否会加锁主要取决于你使用的是哪种类型的Dictionary。在.NET框架中,有两种主要的Dictionary实现:

  1. System.Collections.Generic.Dictionary<TKey, TValue>‌:这是非线程安全的。这意味着如果你在多线程环境下同时对同一个Dictionary实例进行写操作(如添加、删除、修改元素),你需要自己手动管理线程安全。

  2. System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>‌:这是线程安全的。ConcurrentDictionary<TKey, TValue>提供了内置的线程安全机制,允许多个线程同时访问和修改集合而不需要额外的锁。

如果你使用的是System.Collections.Generic.Dictionary<TKey, TValue>

如果你决定使用普通的Dictionary,并且需要在多线程环境下安全地操作它,你有以下几种选择:

新手可能认为 Mutex 更"强大"

public readonly static Mutex mutex = new Mutex(); // 其实过重
而有经验的开发者会用:
private static readonly object _lockObj = new object();
lock(_lockObj) { ... }

Mutex 比 lock 更重量级:

  • Mutex:内核级对象,上下文切换开销大

  • lock:用户态同步,性能更好

public static Dictionary<string, DateTime> RemoteLinkStatue = new Dictionary<string, DateTime>();/// <summary>
/// 读取操作加锁,跨线程
/// </summary>
public readonly static Mutex readRemoteLinkStatueMutex = new Mutex();App.readRemoteLinkStatueMutex.WaitOne();
try 
{if (App.RemoteLinkStatue.ContainsKey(remoteIp)) App.RemoteLinkStatue[remoteIp] = DateTime.Now;else App.RemoteLinkStatue.Add(remoteIp, DateTime.Now);
}
finally 
{App.readRemoteLinkStatueMutex.ReleaseMutex();
}

更好的替代方案

方案1:使用 lock(推荐)

你可以使用lock语句来确保对字典的访问是线程安全的。例如:

private static readonly object _dictionaryLock = new object();lock(_dictionaryLock) 
{if (App.RemoteLinkStatue.ContainsKey(remoteIp)) App.RemoteLinkStatue[remoteIp] = DateTime.Now;else App.RemoteLinkStatue.Add(remoteIp, DateTime.Now);
}
方案2:使用 ConcurrentDictionary(最佳)

使用ConcurrentDictionary<TKey, TValue>‌:如果你经常需要在多线程环境中使用字典,并且对性能有较高要求,可以考虑使用ConcurrentDictionary

private static ConcurrentDictionary<string, DateTime> _myConcurrentDictionary = new ConcurrentDictionary<string, DateTime>();public void AddItem(string key, DateTime value)
{// 无需手动加锁,方法本身是原子的、线程安全的_myConcurrentDictionary.TryAdd(key, value);
}// 原子性操作
RemoteLinkStatus.AddOrUpdate(remoteIp, DateTime.Now, (key, oldValue) => DateTime.Now);

总结

对于纯跨线程的场景,使用 Mutex 是过度设计

  • 单线程环境或只读访问 -> 使用 Dictionary,无需锁。

  • 如果你的应用是多线程的,并且对性能有较高要求,推荐使用ConcurrentDictionary<TKey, TValue>
  • 如果出于某种原因你不得不使用普通的Dictionary<TKey, TValue>,确保通过适当的同步机制(如锁)来保护对字典的访问。

选择合适的集合类型和同步策略对于确保应用程序的稳定性和性能至关重要

http://www.dtcms.com/a/512406.html

相关文章:

  • 企业im聊天软件支持什么功能,应该怎么选?
  • 【Linux系统编程】权限的概念
  • githup网站建设网站营销站点有你想
  • 差分|递归
  • 如何通过纺织服装MES系统提升生产效率和管理水平?
  • 打通智慧高速核心系统:湖南某新建项目的收费、通信、监控一体化实践
  • 河南网站建设优化技术福建省建设干部网站
  • 智能机器人:今年双十一“减人增效”的AI智能客服机器人方案
  • 市环保局网站建设方案建站公司哪家好 知道万维科技
  • 房产中介网站建设的目的cms 美容网站 模版
  • vue开发中,如果出现了反显数据有问题(后端明明返回的有数据,但就是不反显,没有值)是什么原因
  • 【2025-系统规划与管理师】第12章:信息系统服务管理
  • C++---嵌套类型(Nested Types)封装与泛型的基石
  • Floyd判圈算法(Floyd Cycle Detection Algorithm)
  • 网站建设支付宝温州建设学校网站
  • 深圳网站制作 优选灵点网络前端开发语言有哪些
  • .NET8 通过自定义类映射appsettings.json 文件某个节点的配置
  • 25-DAPO: An Open-Source LLM Reinforcement LearningSystem at Scale
  • 6个网站建设网站设置保存登录密码怎么取消
  • 网站建设和维护的职责网站开发工程师有证书考试吗
  • 网站建设计算机人员招聘策划营销方案
  • 《i.MX6ULL LED 驱动实战:内核模块开发与 GPIO 控制》
  • Effective Java学习笔记:用静态工厂方法代替构造器(第一条)
  • TDengine 数学函数 POW 用户手册
  • AI大模型“战国策”:主流LLM平台简单介绍
  • Prometheus监控部署——pushgateway自动推送
  • 网站布局优化问问建设网站的人
  • 做网站宜宾深圳龙华网站建设公司
  • vue3 setup的平级函数(宏函数)
  • 企业门户网站开发代码游戏公司网站模板下载