我目前正在编写一些对性能至关重要的代码,这些代码需要一种无需使用锁即可从键值存储中检索值的方法。
我曾尝试使用 ConcurrentDictionary,但在这种情况下,它的性能不足以满足我的需求。
所以我在这里追求的是类似于 ConcurrentDictionary 中的 GetOrAdd 方法,但我需要它超级快(没有锁)并且仍然是线程安全的:)
这里应该注意的是,假设我们将主要检索现有值而很少添加新值。还假设此列表不会很大。
我不是线程专家,所以如果有人可以评论我的想法,那就太好了。
public class Registry<TKey, TValue>
{
private Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();
public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
{
TValue value;
if (!dictionary.TryGetValue(key, out value))
{
var snapshot = new Dictionary<TKey, TValue>(dictionary);
if (!snapshot.TryGetValue(key, out value))
{
value = valueFactory(key);
snapshot.Add(key, value);
dictionary = snapshot;
}
}
return value;
}
}
这里的“技巧”是创建实际字典的快照,如果我们确实需要向它添加新值。最后,我们交换引用,以便字典变量现在指向快照。请记住,我真的不在乎我是否在这里和那里丢失一两个更新。我需要的是真正快速检索现有值。
我对交换引用的代码有点不确定。
字典=快照;
如果另一个线程在交换引用的同时尝试访问字典变量会发生什么。这甚至是一个问题吗?
问候
伯恩哈德·里希特