我有这样一个班级:
public static class CacheManager
{
static object lockObject = new object();
static MemcachedClient CacheObject
{
get
{
if (!MemcachedClient.Exists(Settings.Default
.CacheInstanceName))
{
MemcachedClient.Setup(Settings.Default
.CacheInstanceName,
new string[] {Settings.Default
.CacheHostAddress});
}
//
//
return MemcachedClient.GetInstance(Settings
.Default.CacheInstanceName);
}
}
public static List<TData> Get<TData>(string key, Func<List<int>> getListCallback,
Func<int, TData> getItemCallback) where TData : class
{
var result = new List<TData>();
//
//
var list = CacheObject.Get(key);
if (list == null)
{
lock (lockObject)
{
list = CacheObject.Get(key);
if (list == null)
{
list = getListCallback();
CacheObject.Set(key, list);
//
//
foreach (var id in (List<int>)list)
{
var item = getItemCallback(id);
result.Add(item);
CacheObject.Set(string.Concat(key, id), item);
}
}
}
}
else
{
foreach (var id in (List<int>)list)
{
var itemKey = string.Concat(key, id);
//
//
var item = CacheObject.Get(itemKey);
if (item == null)
{
lock (lockObject)
{
item = CacheObject.Get(itemKey);
if (item == null)
{
item = getItemCallback(id);
CacheObject.Set(itemKey, item);
}
}
}
//
//
result.Add((TData)item);
}
}
//
//
return (List<TData>)result;
}
public static void Remove(string key)
{
CacheObject.Delete(key);
}
}
它在类库中使用:
public class NewsRepository : BaseRepository, IRepository
{
public List<News> FindAll()
{
return CacheManager.Get<News>(key,
() => clientEntities.News.OrderByDescending(n => n.DateCreated).Select(n => n.NewsId).ToList(),
(id) => clientEntities.News.Single(n => n.NewsId == id));
}
}
public class PagesRepository : BaseRepository
{
public List<Page> FindAll()
{
return CacheManager.Get<Page>(key,
() => clientEntities.Pages.OrderBy(p => p.PageId).Select(p => p.PageId).ToList(),
(id) => clientEntities.Pages.Single(p => p.PageId == id));
}
}
我的问题是:例如,NewsRepository没有在缓存中找到新闻并获得锁定并开始加载数据,但此时PagesRepository没有在缓存中找到页面。 PagesRepository的CacheManager会被NewsRepository锁定还是(我认为是这样)NewsRepository的CacheManager是另一个静态类,它的内部锁不会触及PagesRepository的CacheManager?
答案 0 :(得分:13)
非泛型类型的静态字段(本身不嵌套在泛型类型中等)只存在一次,因此所有锁都会发生冲突。
如果(注释)你的目标是使每个类型的锁(来自通用方法),那么最好的方法是:
public static class CacheManager {
static class TypeLock<T> {
public static readonly object SyncLock = new object();
}
...
void SomeGenericMethod<TData>(args) {
...
lock(TypeLock<TData>.SyncLock) {
...
}
...
}
}
此处,SyncLock
每T
只存在一次(且仅一次),因此每TData
。这样您就可以保留现有的API(CacheManager
不是通用的)。
答案 1 :(得分:5)
两者都将对lockObject使用相同的引用,因此使用相同的锁。