c# 锁定泛型函数

标签 c# multithreading generics 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);
    }
}

它在类库中使用:

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?

最佳答案

非泛型类型的静态字段(它本身没有嵌套在泛型类型等中)只存在一次,所以所有的锁都会发生冲突。

如果(评论)您的目标是针对每个类型进行锁定(通过泛型方法),那么最好的方法可能是:

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 是非通用的)。

关于c# 锁定泛型函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8411838/

相关文章:

c# - DI Singleton 实例与 Transient 实例

c# - Excel 上的 OLEDB 查询不带标题 : How do I specify Columns?

java - 在一定时间段后中断未知的长时间运行的函数

c# - 如何通过重载使用泛型?

c# - 为什么 AutoMapper 有一个 IValueFormatter,而它有一个看似更强大的 ValueResolver?

c# - Azure函数应用程序、服务总线和返回服务总线

c++ - 锁定资源(线程,C++)

.net - 等待(GetAwaiter)和ContinueWith有什么区别

scala - 在方法中使用类型参数实现特征

java - 如果在集合实例化期间未指定类型参数之一,会发生什么情况?