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

本文关键字:实现 锁定 控制器 缓存 共享 | 更新日期: 2023-09-27 18:10:59

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

代码如下:

 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;
    }

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

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

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

问题是:我怎样才能做到?

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

为每个用户使用一个Sync对象将违背同步的目的,因为每次使用都会持有自己的锁,并且对于同一个cacheId,您将有可能最终多次调用该方法。这可能导致数据变得不一致。

如果你希望每个用户保持一个同步对象,那么最好使用会话变量或每个用户缓存或类似的东西。否则每个用户最终都会弄乱彼此的cacheId结果。

如果你有一个场景,当有多个阅读器的数据,但在同一时间一个用户可以写它,然后尝试使用ReaderWriterLockSlim。与锁定多用户场景相比,这是非常快的。

Update1

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

这里不需要锁。原因,HttpContext。缓存是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;
            }
        }