【发布时间】:2013-08-24 10:33:07
【问题描述】:
我正在编写一个面向 .NET 4.5、Windows Store 应用程序和 Windows Phone 8 的可移植类库。我需要一种高效的内存缓存机制,所以我正在考虑使用 ConcurrentDictionary<K,V>,但它在WP8。
会有很多读取和相对较少的写入,所以理想情况下,我想要一个支持多线程无锁读取和单线程写入的集合。非泛型 Hashtable 具有该属性 according to MSDN,但不幸的是它在 PCL 中不可用...
PCL 中是否有其他可用的集合类符合此要求?如果不是,那么在不锁定读取的情况下实现线程安全的好方法是什么? (锁定写入是可以的,因为它不会经常发生)
编辑:感谢 JaredPar 的指导,我最终以完全无锁的方式实现了我的缓存,使用来自 Microsoft.Bcl.Immutable 的 ImmutableDictionary<TKey, TValue>:
class Cache<TKey, TValue>
{
private IImmutableDictionary<TKey, TValue> _cache = ImmutableDictionary.Create<TKey, TValue>();
public TValue GetOrAdd(TKey key, [NotNull] Func<TKey, TValue> valueFactory)
{
valueFactory.CheckArgumentNull("valueFactory");
TValue newValue = default(TValue);
bool newValueCreated = false;
while (true)
{
var oldCache = _cache;
TValue value;
if (oldCache.TryGetValue(key, out value))
return value;
// Value not found; create it if necessary
if (!newValueCreated)
{
newValue = valueFactory(key);
newValueCreated = true;
}
// Add the new value to the cache
var newCache = oldCache.Add(key, newValue);
if (Interlocked.CompareExchange(ref _cache, newCache, oldCache) == oldCache)
{
// Cache successfully written
return newValue;
}
// Failed to write the new cache because another thread
// already changed it; try again.
}
}
public void Clear()
{
_cache = _cache.Clear();
}
}
【问题讨论】:
-
您是否考虑过编写一种包装不可变树的类型,并为写入做了 CAS?这将为您提供无锁读取、CAS 写入,您可以使用 Eric 的不可变 AVL 树作为支持结构blogs.msdn.com/b/ericlippert/archive/2008/01/21/…
-
@JaredPar,什么是“CAS”?
-
CAS = 比较和交换。
-
谢谢,我会调查的。但是每次我需要添加东西时复制树不是很昂贵吗?
-
MSDN 说 ConcurentDictionary is in the PCL...
标签: c# caching collections concurrency thread-safety