如何在共享缓存控制器中实现锁定?

时间:2014-06-30 11:35:07

标签: c# caching locking

我有一个静态类,用于处理常用数据的缓存读/写。

代码是这样的:

 public static T GetFromCache<T>(double seconds, string cacheId, Func<T> method) where T : class
    {
        HttpContext ctx = HttpContext.Current;
        object temp = null;
        temp = ctx.Cache[cacheId];

        if (temp == null)
        {
            lock (Sync)
            {
                temp = ctx.Cache[cacheId];
                if (temp == null)
                {
                    temp = method.Invoke();
                    AddToCache(temp as T, seconds, cacheId);
                    return temp as T;
                }

            }
        }

        if (temp is T)
        {
            return (T)temp;
        }
        return null;
    }

各种调用者使用该代码从缓存中读取数据并将数据写入缓存。 现在我有一个Sync对象(private static readonly object Sync = new object();),当数据写入缓存时会被锁定。

由于此代码由多个调用者调用,我想创建一个Sync对象列表,每个调用者一个。 (使用调用者我不是指用户,而是调用代码。然后我会通过参数caller的签名来识别method 我想要的原因是每一段调用代码都可以拥有它自己的锁对象;否则(我认为)来自不同调用者的每个对此缓存控制器的调用将使用相同的锁对象。然后,国家列表的缓存也将锁定状态列表的缓存,并且使用两个不同的锁定对象,它们将不会彼此相同。

然后我会使用CacheItemRemovedCallback方法从列表中删除锁定项。

问题是:我该怎么做?

1 个答案:

答案 0 :(得分:1)

通过为每个用户设置一个Sync对象将违反同步的目的,因为每个用户将拥有自己的锁,并且有可能对于相同的cacheId,您将最终多次调用该方法。这可能会导致数据不一致。

如果您希望为每个用户保留一个Sync对象,那么利用会话变量或每个用户缓存或类似的东西是好的。否则每个用户实际上最终会互相搞砸&#39; s cacheId结果。

如果你有一个场景,可以有多个数据读者,但一次只有一个用户可以写,然后尝试使用ReaderWriterLockSlim。与多用户场景中的锁定相比,这非常快。

<强> UPDATE1

考虑到cacheId是唯一的,并且在调用者之间不常见。您可以使用以下代码。

这里不需要锁定。原因,HttpContext.Cache是​​ThreadSafe。意思是,您可以读取/保存值到Cache。但是,如果值引用本身在多个并发调用之间共享,那么请同步它。

 public static T GetFromCache<T>(double seconds, string cacheId, Func<T> method) where T : class
        {
            HttpContext ctx = HttpContext.Current;
            object temp = null;
            temp = ctx.Cache[cacheId];
            if (temp == null)
            {
                temp = method.Invoke();
                AddToCache(temp as T, seconds, cacheId);
                return temp as T;
            }
        }

此致