可移植类库的ConcurrentDictionary的替代方案
本文关键字:方案 ConcurrentDictionary 类库 可移植 | 更新日期: 2023-09-27 18:28:42
我正在编写一个针对.NET 4.5、Windows应用商店应用程序和Windows Phone 8的可移植类库。我需要一个高效的内存缓存机制,所以我考虑使用ConcurrentDictionary<K,V>
,但它在WP8中不可用。
会有很多读取和相对较少的写入,所以理想情况下,我想要一个支持从多个线程进行无锁读取并由单个线程进行写入的集合。根据MSDN的说法,非通用Hashtable
具有该属性,但不幸的是,它在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以无锁方式完成。这将比ConcurrentDictionary
慢一点,因为查找是O(Log(N))而不是接近O(1)。但它应该为你的