首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对象-缓存通用锁定

对象-缓存通用锁定
EN

Stack Overflow用户
提问于 2015-06-15 08:05:58
回答 1查看 170关注 0票数 0

我有一个缓存对象缓存,所述缓存可以容纳多个类型,并且每当给定{T}被访问时,我都想对所述{T}添加一个锁。

我的实施:

代码语言:javascript
复制
    readonly static IDictionary<Type, List<object>> _cache = new ConcurrentDictionary<Type, List<object>>();

    private static List<object> FindTypeInCache(Type type)
    {
        List<object> list;
        if (_cache.TryGetValue(type, out list))
        {
            return list;
        }
        else
        {
            _cache[type] = new List<object>();
        }

        return new List<object>();
    }

    public static T FindFirstBy<T>(Func<T, bool> predicate) where T : class
    {
        // Is this a valid lock locking only _cache[T] ? And not _cache as whole?
        lock (_cache[typeof(T)])
        {
            return FindTypeInCache(typeof(T)).Cast<T>().Where(predicate).FirstOrDefault();
        }
    }

    public static bool AddOrUpdate<T>(Func<T, bool> predicate, T entity) where T : class
    {
        lock (_cache[typeof(T)])
        {
            // Find Type cache.
            List<object> list = FindTypeInCache(typeof(T));

            // Look for old entity.
            var e = list.Cast<T>().Where(predicate).FirstOrDefault();

            // If no old record exists no problem we treat this as if its a new record.
            if (e != null)
            {
                // Old record found removing it.
                list.Remove(e);
            }

            // Regardless if object existed or not we add it to our Cache.
            list.Add(entity);
            _cache[typeof(T)] = list;
        }
    }

在访问时,我的实现是否只正确地锁定了_cacheT,而不是整个_cache作为一个整体?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-15 08:14:36

你的代码有很多奇怪(或完全错误)的地方。

首先,您使用的是ConcurrentDictionary,但不是将其用作并发字典。例如,要初始化列表,可以使用GetOrAddMethod

代码语言:javascript
复制
private static List<object> FindTypeInCache(Type type)
{
    return _cache.GetOrAdd(type, () => new List<object>());
}

简单和线程安全:)

其次,您正在锁定_cache[type] --但是即使缓存中没有这样的类型。这意味着一个KeyNotFoundException

第三,使用锁保护的唯一代码是读取。但这很可能还不够--至少,您还需要使用相同的锁来保护写入(特别是考虑到上面的点),并且取决于返回值的实际用法,返回值的突变(如果它确实是可变的,也可以读取该可变值)。

换句话说,您只保护了实际上不需要保护的代码(如果您使用正确的方法更新字典)!围绕lock等的额外Where可能会稍微有所帮助,但它肯定不能保证List访问的安全性。

所有这一切,也许有一个更好的解决办法。您使用的是使用通用方法的缓存。为什么不使缓存本身成为通用的呢?这样,首先您将避免使用字典,因为存储在字典中的每个泛型类型都将得到它们自己的类型--这也意味着您可以在静态构造函数中安全地初始化List<T>。任何锁定也可以安全地应用于对特定通用缓存的所有访问,而不是您现在拥有的“聚合”缓存。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30840178

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档