静态字典缓存的.NET线程安全 [英] .NET Thread Safety for Static Dictionary Cache

查看:153
本文介绍了静态字典缓存的.NET线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的ASP.NET Web应用程序中,对页面的所有请求都访问此公共静态缓存类. (因此它必须是线程安全的)

In my ASP.NET Web application, all the requests to pages access this common static cache class. (So it has to be thread safe)

通过调用Cache类的Refresh方法(如下所述)来刷新此缓存是否安全. 还是会导致同步问题?

Is it safe to refresh this cache by calling the Refresh method of Cache class as implemented below. Or it causes sync problems?

    static class Cache
    {
        static Dictionary<string, string> cachedCodeNames;
        static readonly object sync = new object();

        public static string GetName(string code)
        {
            return CodeNames[code];
        }

        public static void Refresh()
        {
            cachedCodeNames = null;
        }

        static Dictionary<string, string> CodeNames
        {
            get
            {
                if (cachedCodeNames == null)
                {
                    lock (sync)
                    {
                        if (cachedCodeNames == null)
                        {
                            cachedCodeNames = WebServiceManager.GetCodeNameCache();
                        }
                    }
                }
                return cachedCodeNames;
            }
        }
    }

    static class WebServiceManager
    {
        internal static Dictionary<string, string> GetCodeNameCache()
        {
            throw new NotImplementedException();
        }
    }

推荐答案

这里肯定存在竞争条件.如果一个线程刚刚退出lock,然后另一个线程调用(并完成)Refresh,则第一个线程将从CodeNames返回null.如果从GetName内部读取了CodeNames,则将立即生成NullReferenceException.

There's certainly a race condition here. If one thread has just stepped out of the lock and at that point another thread calls (and completes) Refresh, the first thread is going to return null from CodeNames. If CodeNames was being read from inside GetName, this will immediately result in a NullReferenceException.

为防止这种情况,您需要使用lock(sync)保护Refresh或像这样重写CodeNames:

To prevent this, you 'd need to either protect Refresh with a lock(sync) or rewrite CodeNames like this:

lock (sync)
{
    if (cachedCodeNames == null)
    {
        var codeNames = WebServiceManager.GetCodeNameCache();
        cachedCodeNames = codeNames;
        return codeNames;
    }
}

当然,在这种情况下,您应该进行大量评论,以表明这种看似毫无意义的仪式实际上是一项重要功能.

Of course in this case you should apply generous amounts of comments to make clear that this seemingly pointless ritual is in fact an important feature.

这篇关于静态字典缓存的.NET线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆