gpt4 book ai didi

c# - ConcurrentDictionary线程安全替代方案中的AddOrUpdate方法

转载 作者:行者123 更新时间:2023-12-03 13:23:24 27 4
gpt4 key购买 nike

按照此页面“备注”部分中的Is AddOrUpdate thread safe in ConcurrentDictionary?链接https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx。它说

"However, delegates for these methods are called outside the locks toavoid the problems that can arise from executing unknown code under alock. Therefore, the code executed by these delegates is not subjectto the atomicity of the operation."


问题是我在我的代码中广泛使用了该代码,并意识到我有一个潜在的非常讨厌的错误(我的理解一直以来都是错误的)...因为在使用下面的方式时,我没想到可以在同时覆盖内部字典:
internal class HandlerProducers
{
readonly ConcurrentDictionary<Type, Dictionary<Type, InstanceProducer>> handlerProducers
= new ConcurrentDictionary<Type, Dictionary<Type, InstanceProducer>>();

public void AddProducer(Type notificationType, Type concreteType, InstanceProducer producer)
{
this.handlerProducers
.AddOrUpdate(
notificationType,
(key) => new Dictionary<Type, InstanceProducer> { { concreteType, producer } },
(key, dictionary) => { dictionary.Add(concreteType, producer); return dictionary; });
}

public IEnumerable<InstanceProducer> GetForHandler(Type notificationHandlerType)
{
if(this.handlerProducers.TryGetValue(notificationHandlerType, out var dict))
{
foreach (var kvp in dict)
yield return kvp.Value;
}
}
}
我还有一个挑战,就是天真地将锁置于适当位置可能会引起热点,以上类广泛用于通过 GetForHandler()进行读取,并且有时会被写入(通过 AddProducer()方法)。
通过具有大量读取和偶发写入的性能设计人员,确保这是线程安全的最佳方法是什么?

最佳答案

我建议使用嵌套的ConcurrentDictionary结构:

readonly ConcurrentDictionary<Type, ConcurrentDictionary<Type, InstanceProducer>> handlerProducers
= new ConcurrentDictionary<Type, ConcurrentDictionary<Type, InstanceProducer>>();
然后,您可以像这样实现 AddProducer方法:
public void AddProducer(Type notificationType, Type concreteType,
InstanceProducer producer)
{
ConcurrentDictionary<Type, InstanceProducer> innerDict =
this.handlerProducers.GetOrAdd(notificationType,
_ => new ConcurrentDictionary<Type, InstanceProducer>());

if (!innerDict.TryAdd(concreteType, producer))
throw new InvalidOperationException(
$"{notificationType}.{concreteType} already exists.");
}
方法 GetForHandler无需修改。
此实现将使 HandlerProducers类真正具有线程安全性,而不会牺牲其效率。

关于c# - ConcurrentDictionary线程安全替代方案中的AddOrUpdate方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63314627/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com