如何在共享缓存控制器中实现锁定
本文关键字:实现 锁定 控制器 缓存 共享 | 更新日期: 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;
}
}
对