You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# Web应用Dictionary加锁方案咨询:自写加锁写法是否可行?

问题:Dictionary重复添加键报错,加锁方案是否可行?

我的C# Web应用运行时抛出错误:C# System.Collections.Generic.Dictionary2.Insert - An item with the same key has already been added`,排查后确定需要给代码加锁,我尝试了下面的加锁方式,请问这个方案是否可行?

原代码

if (keyVals == null)
{
    keyVals = new Dictionary<string, string>();
}

if (activity != null)
{
    keyVals.Add(string.Format("{0}S1", prefix), test.GetType().FullName);
    keyVals.Add(string.Format("{0}S2", prefix), test.acode);
    keyVals.Add(string.Format("{0}S3", prefix), test.id.ToString());
    keyVals.Add(string.Format("{0}S4", prefix), test.unme);
}
else
{
    keyVals.Add("testtype", "N/A");
}

加锁后的代码

using (new Lock(myLockObject))
{
    if (keyVals == null)
    {
        keyVals = new Dictionary<string, string>();
    }
    
    if (activity != null)
    {
        keyVals.Add(string.Format("{0}S1", prefix), test.GetType().FullName);
        keyVals.Add(string.Format("{0}S2", prefix), test.acode);
        keyVals.Add(string.Format("{0}S3", prefix), test.id.ToString());
        keyVals.Add(string.Format("{0}S4", prefix), test.unme);
    }
    else
    {
        keyVals.Add("testtype", "N/A");
    }
}

回答

这个加锁方案能否生效取决于几个关键前提:

1. 锁对象myLockObject必须正确

myLockObject不能是局部变量,必须是所有并发线程能共享的对象:

  • 如果keyVals是类的实例字段,myLockObject应该是该类的私有实例字段(比如private readonly object _lockObj = new object();)
  • 如果keyVals是静态字段,myLockObject必须是静态私有字段(比如private static readonly object _lockObj = new object();)
    要是锁对象不对,每个线程用自己的锁,根本起不到互斥作用,并发问题还是会出现。

2. 所有对keyVals的操作都要加锁

Dictionary本身完全不是线程安全的,除了这段添加代码,其他任何读写keyVals的地方(比如遍历、修改、读取键值)都必须用同一个myLockObject加锁,否则依然会引发线程安全问题,比如读取时的集合修改异常,或者重复添加键。

3. 先排除单线程内的重复键问题

加锁只能解决并发导致的重复添加,如果单线程内多次执行这段代码,或者prefix重复导致键重复,加锁也没用。这种情况应该把Add换成TryAdd,或者先判断键是否存在:

// 示例:用TryAdd避免单线程内重复添加
if (activity != null)
{
    keyVals.TryAdd(string.Format("{0}S1", prefix), test.GetType().FullName);
    // 其他字段同理
}

总结

如果满足「锁对象是共享的」+「所有keyVals操作都加锁」这两个条件,这个方案能解决并发导致的重复添加问题。但更推荐用.NET自带的ConcurrentDictionary,它本身是线程安全的,不需要手动加锁,用TryAdd或AddOrUpdate方法就能更可靠地处理并发场景。

内容的提问来源于stack exchange,提问作者Techno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 11:07:29