替代ConcurrentDictionary的可移植类库 [英] Alternative to ConcurrentDictionary for portable class library

查看:134
本文介绍了替代ConcurrentDictionary的可移植类库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个以.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆