替代ConcurrentDictionary的可移植类库 [英] Alternative to ConcurrentDictionary for portable class library
问题描述
我正在编写一个以.NET 4.5,Windows应用商店应用和Windows Phone 8为目标的可移植类库。我需要一个高效的内存缓存机制,所以我在考虑使用 ConcurrentDictionary< K ,V>
,但它不适用于WP8。
I'm writing a portable class library that targets .NET 4.5, Windows Store apps and Windows Phone 8. I need an efficient in-memory cache mechanism, so I was thinking about using ConcurrentDictionary<K,V>
, but it's not available in WP8.
会有很多读取和相对较少的写入,所以理想情况下,支持从多个线程进行无锁读取,并由单个线程写入的集合。非通用 Hashtable
具有该属性,根据MSDN ,但不幸的是它不是在PCL ...
There will be many reads and relatively few writes, so ideally I'd like a collection that supports lock-free reads from multiple threads, and write by a single thread. The non-generic Hashtable
has that property, according to MSDN, but unfortunately it's not available in the PCL...
有没有另一个集合类可用在PCL符合这个要求?如果没有,什么是一个好的方式来实现线程安全没有锁定的读取? (锁定写入是OK,因为它不会太频繁)
Is there another collection class available in the PCL that matches this requirement? If not, what would be a good way to achieve thread safety without locking for reads? (locking for writes is OK, since it won't happen too often)
编辑:感谢JaredPar的指导,最终使用 ImmutableDictionary< TKey,TValue> 以完全无锁的方式实现了我的缓存Microsoft.Bcl.Immutable> Microsoft.Bcl.Immutable :
thanks to JaredPar's guidance, I eventually implemented my cache in a completely lock-free fashion, using ImmutableDictionary<TKey, TValue>
from Microsoft.Bcl.Immutable:
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();
}
}
推荐答案
选项考虑是在不变的搜索树上写一个薄的外观。有几个不可变的搜索树可在网上选择。我通常把Eric Lipperts的主题放在这个主题上。
One option to consider is to write a thin facade over an immutable search tree. There are several immutable search trees available on the web to choose from. I usually base mine off of Eric Lipperts great post on the subject
- Immutable Binary Search Tree
使用此作为后备数据结构将使您无锁。写入树可以使用CAS以锁定自由的方式完成。这将比 ConcurrentDictionary
慢一点,因为查找是O(Log(N))而不是接近O(1)。但它应该为你
Using this as the backing data structure will give you lock free. Writes to the tree can be done in a lock free fashion with CAS as well. This will be a bit slower than ConcurrentDictionary
because lookups are O(Log(N)) instead of approaching O(1). But it should do the trick for you
这篇关于替代ConcurrentDictionary的可移植类库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!