我正在尝试实现通用缓存管理器,但是我不确定如何进行锁定。
到目前为止我有以下内容,但是如果我有两个具有相同返回类型的缓存条目,那么我猜测将使用相同的锁定对象!
public class CacheManager : ICacheManager
{
static class TypeLock<T>
{
public static readonly object SyncLock = new object();
}
private readonly ICache _cache;
public CacheManager(ICache cache)
{
if (cache == null)
throw new ArgumentNullException("cache");
_cache = cache;
}
public TResult AddCache<TResult>(string cacheKey, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
{
return AddCache(cacheKey, null, acquire, cacheDurationInMinutes);
}
public TResult AddCache<TResult>(string cacheKey, CacheDependency dependency, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
{
var entry = acquire.Invoke();
if (entry != null)
{
if (dependency != null)
_cache.InsertWithDependency(cacheKey, entry, dependency, DateTime.Now.AddMinutes(cacheDurationInMinutes));
else
_cache.Insert(cacheKey, entry, DateTime.Now.AddMinutes(cacheDurationInMinutes));
}
return entry;
}
public TResult GetOrAddCache<TResult>(string cacheKey, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
{
return GetOrAddCache(cacheKey, null, acquire, cacheDurationInMinutes);
}
public TResult GetOrAddCache<TResult>(string cacheKey, CacheDependency dependency, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
{
var entry = _cache.GetItem(cacheKey) as TResult;
if (entry == null)
{
lock (TypeLock<TResult>.SyncLock)
{
entry = _cache.GetItem(cacheKey) as TResult;
if (entry == null)
{
entry = acquire.Invoke();
if (entry != null)
{
if (dependency != null)
_cache.InsertWithDependency(cacheKey, entry, dependency,
DateTime.Now.AddMinutes(cacheDurationInMinutes));
else
_cache.Insert(cacheKey, entry, DateTime.Now.AddMinutes(cacheDurationInMinutes));
}
}
}
}
return entry;
}
}
非常感谢任何帮助!
答案 0 :(得分:1)
你是对的,这会对同一类型的所有缓存条目使用相同的锁。为了保持独立于此缓存管理器的实际缓存方法(内存,文件,数据库...),我建议为每个缓存条目存储一个额外的同步对象,因此您的缓存条目将查找例如Tuple<object, TResult>
而不是TResult
只需object
,其中new object()
对于每个条目都是{{1}},并将用于锁定。
答案 1 :(得分:1)
除非真的需要,否则你永远不应该锁定你的缓存代码。 如果您不想使用任何众所周知的缓存,请使用Concurrent字典。
我还说你可能应该使用System.Runtime.MemorCache
代替。
或者您使用的解决方案可以为您抽象, 比如我的CacheManager https://github.com/MichaCo/CacheManager;)
答案 2 :(得分:0)
我不确定你应该使用lock,alos,为什么不使用MemoryCache而不是ICache接口?内存缓存不够通用吗? 为什么强制缓存时间是分钟,你应该将时间跨度传递给缓存方法,我会更通用。
几个月前我实施了a version of a cache manager,但它是面向网络的。