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

ConcurrentDictionary.GetOrAdd嵌套集合场景下的线程安全疑问

ConcurrentDictionary.GetOrAdd 嵌套集合场景的线程安全行为解析

核心行为说明

当多线程同时针对同一个不存在的key调用GetOrAdd时:

  • 所有竞争线程都会执行你传入的工厂方法(即new ConcurrentBag<TaskCompletionSource<string>>()),也就是会临时创建多个ConcurrentBag实例。
  • 但最终只有一个线程创建的实例会被成功存入ConcurrentDictionary,其他线程创建的实例会被直接丢弃(成为垃圾回收对象)。
  • 关键:所有线程调用GetOrAdd后得到的返回值,都是那个被成功存入字典的ConcurrentBag实例——不管这个实例是不是当前线程自己创建的。

你的代码实际表现

对应你这段代码:

var completions = subscribers.GetOrAdd(key, _ => new ConcurrentBag<TaskCompletionSource<string>>());
completions.Add(completion);
  • 完全符合你的期望:所有线程最终都会拿到同一个ConcurrentBag实例,并向其中添加元素,不会出现元素“丢失”的情况。
  • 唯一的额外开销是:竞争期间会多创建几个无用的ConcurrentBag实例,但这些实例会被垃圾回收,不会影响业务逻辑的正确性。

为什么不会出问题

因为GetOrAdd的内部实现保证了,无论有多少个线程执行了工厂方法,最终返回给所有调用者的都是字典中实际存储的那个值。所以后续的Add操作都是针对同一个线程安全的ConcurrentBag,自然能保证所有元素都被正确添加到同一个集合里。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:17:42