c#锁定通用函数
我有这样一门课:c#锁定通用函数,c#,multithreading,generics,locking,C#,Multithreading,Generics,Locking,我有这样一门课: public static class CacheManager { static object lockObject = new object(); static MemcachedClient CacheObject { get { if (!MemcachedClient.Exists(Settings.Default .CacheInstanceName))
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);
}
}
公共静态类缓存管理器
{
静态对象lockObject=新对象();
静态MemcachedClient缓存对象
{
得到
{
如果(!MemcachedClient.Exists)(Settings.Default
.CacheInstanceName)
{
MemcachedClient.Setup(Settings.Default
.CacheInstanceName,
新字符串[]{Settings.Default
.CacheHostAddress});
}
//
//
返回MemcachedClient.GetInstance(设置
.Default.CacheInstanceName);
}
}
公共静态列表Get(字符串键,Func getListCallback,
Func getItemCallback),其中TData:class
{
var result=新列表();
//
//
var list=CacheObject.Get(key);
if(list==null)
{
锁定(锁定对象)
{
list=CacheObject.Get(key);
if(list==null)
{
list=getListCallback();
CacheObject.Set(键,列表);
//
//
foreach(列表中的变量id)
{
var item=getItemCallback(id);
结果.添加(项目);
CacheObject.Set(string.Concat(key,id),item);
}
}
}
}
其他的
{
foreach(列表中的变量id)
{
var itemKey=string.Concat(key,id);
//
//
var item=CacheObject.Get(itemKey);
如果(项==null)
{
锁定(锁定对象)
{
item=CacheObject.Get(itemKey);
如果(项==null)
{
item=getItemCallback(id);
CacheObject.Set(itemKey,item);
}
}
}
//
//
结果。添加((TData)项);
}
}
//
//
返回(列表)结果;
}
公共静态无效删除(字符串键)
{
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));
}
}
公共类新闻存储库:BaseRepository,IRepository
{
公共列表FindAll()
{
返回CacheManager.Get(键,
()=>clientEntities.News.OrderByDescending(n=>n.DateCreated)。选择(n=>n.NewsId)。ToList(),
(id)=>cliententies.News.Single(n=>n.NewsId==id));
}
}
公共类页面存储库:BaseRepository
{
公共列表FindAll()
{
返回CacheManager.Get(键,
()=>cliententies.Pages.OrderBy(p=>p.PageId)。选择(p=>p.PageId)。ToList(),
(id)=>cliententies.Pages.Single(p=>p.PageId==id));
}
}
我的问题是:例如,NewsRepository没有在缓存中找到新闻并获得锁并开始加载数据,但此时PagesRepository没有在缓存中找到页面。PagesRepository的CacheManager会被NewsRepository锁定吗?或者(我想是的)NewsRepository的CacheManager是另一个静态类,它的内部锁不会接触PagesRepository的CacheManager?两者都会使用对lockObject的相同引用,因此使用相同的锁。非泛型的静态字段(它本身不嵌套在泛型类型等中)只存在一次,因此所有锁都会冲突 如果(注释)您的目标是针对每个类型(从泛型方法)创建锁,那么最好的方法可能是:
public static class CacheManager {
static class TypeLock<T> {
public static readonly object SyncLock = new object();
}
...
void SomeGenericMethod<TData>(args) {
...
lock(TypeLock<TData>.SyncLock) {
...
}
...
}
}
公共静态类缓存管理器{
静态类类型锁{
公共静态只读对象SyncLock=新对象();
}
...
void SomeGenericMethod(args){
...
锁(TypeLock.SyncLock){
...
}
...
}
}
在这里,
SyncLock
每T
存在一次(并且只存在一次),因此每TData
存在一次。这允许您保留现有的API(其中CacheManager
是非通用的).但如果我将所有CacheManager类都设置为泛型?如果CacheManager是泛型的,则有一个按泛型类型划分的lockObject。CacheManager.lockObject!=CacheManager.lockObject上面的注释是否应以“如果CacheManager是泛型的,…”开头?@MarcGravel嗯,是的,我错了。谢谢你指出这一点。但不知怎么的,我似乎无法再编辑这条评论了……小心双重检查锁定。保存你正在检查的值是否为null的内存需要声明为volatile,否则CLR内存模型不能保证无序的内存写入会发生工作正常。因此我避免了双重检查锁。@RickNZ,你说的是以下内容?| var list=CacheObject.Get(key);if(list==null){lock(lockObject){list=CacheObject.Get(key);if(list==null){…|你能详细描述一下这个问题,或者给我一些链接来阅读吗?是的,这就是我所说的代码。看到了吗