don*_*tta 5 c# generics multithreading locking
我有这样一堂课:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
它在类库中使用:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:例如,NewsRepository没有在缓存中找到新闻并获得锁定并开始加载数据,但此时PagesRepository没有在缓存中找到页面.PagesRepository的CacheManager会被NewsRepository锁定还是(我想是这样)NewsRepository的CacheManager是另一个静态类,它的内部锁不会触及PagesRepository的CacheManager?
Mar*_*ell 13
非泛型类型的静态字段(本身不嵌套在泛型类型中等)只存在一次,因此所有锁都会发生冲突.
如果(注释)你的目标是使每个类型的锁(来自通用方法),那么最好的方法是:
public static class CacheManager {
static class TypeLock<T> {
public static readonly object SyncLock = new object();
}
...
void SomeGenericMethod<TData>(args) {
...
lock(TypeLock<TData>.SyncLock) {
...
}
...
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,SyncLock每次存在一次(并且只存在一次)T,所以每次存在TData.这允许您保留现有的API(CacheManager非通用的).
| 归档时间: |
|
| 查看次数: |
1435 次 |
| 最近记录: |