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){…|你能详细描述一下这个问题,或者给我一些链接来阅读吗?是的,这就是我所说的代码。看到了吗