我已经读过这个问题,但我仍然不明白如果我有一个嵌套集合,GetOrAdd 是如何工作的。
ConcurrentDictionary.GetOrAdd 真的是线程安全的吗?
如果我还没有创建嵌套集合,并且从多个线程同时调用 GetOrAdd,会发生什么? 我期望这样的行为:只有一个线程能够创建一个新集合,其余线程将接收已创建的集合并在那里添加一个值。事情会是这样吗?
var completions = subscribers.GetOrAdd(key, _ => new ConcurrentBag<TaskCompletionSource<string>>());
completions.Add(completion);
我期望只有一个线程能够创建一个新集合的行为,
不完全是。完全有可能有多个线程创建一个新的
TValue
,但只有这些 TValue
之一会添加到字典中。其他 TValue
将超出范围并被丢弃(垃圾收集)。
其余的将收到已经创建的并在那里添加一个值。
是的,所有线程都会与同一个
TValue
进行交互。 GetOrAdd
返回由赢得乐观锁定竞赛的线程创建的 TValue
。竞争是乐观的,因为 valueFactory
委托是在 ConcurrentDictionary<TKey,TValue>
集合内部使用的锁之外调用的。该集合不允许悲观锁定,即您不能使用其内部锁来保护您自己的代码。悲观锁定在某些情况下可能是有益的,但此集合根本不支持此功能。