C# 静态属性锁定

发布于 2024-08-13 05:18:30 字数 741 浏览 4 评论 0原文

只是寻找此代码的代码审查。 ASP.net 缓存不是一个选项。静态列表将在每天获得超过 10K 页面浏览量的网站上被大量访问,并且可能会发生并发读取尝试。在重建列表时重新启动应用程序时,我想知道是否有任何我可能忽略的问题?锁定正在实例化的列表是最佳实践吗?

public class MyClass
{
        private static List<Entry> _listCache = null; 
        protected static List<Entry> ListCache
        {
            get
            {

                if (_listCache == null)
                {
                    _listCache = new List<Entry>();
                    lock (_listCache)
                    {
                        //Add items to the list _listCache from XML file
                    }
                }
                return _listCache;
            }
        }
        //....Other methods that work with the list
}

Just looking for a code review of this code. ASP.net Cache is not an option. The static list will be accessed a lot on a website that gets well over 10K page views per day and concurrent read attempts is likely. On app restart when the list is rebuilt I was wondering if there are any issues I may be overlooking? Is locking on the list being instantiated best practice?

public class MyClass
{
        private static List<Entry> _listCache = null; 
        protected static List<Entry> ListCache
        {
            get
            {

                if (_listCache == null)
                {
                    _listCache = new List<Entry>();
                    lock (_listCache)
                    {
                        //Add items to the list _listCache from XML file
                    }
                }
                return _listCache;
            }
        }
        //....Other methods that work with the list
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

紫﹏色ふ单纯 2024-08-20 05:18:30

10k 次查看 - 每 8 秒一次...不确定您是否需要担心太多...;-p

但是重新编写代码 - 这使事情变得过于复杂,并且您仍然可能最终将其初始化两次。我只是使用静态构造函数来做到这一点;它会更加坚固。如果您必须具有完全隔离的延迟加载(即使在类型上使用其他静态方法),则可以使用内部类来实现相同的效果:

public class MyClass
{
    static class InnerCache {
        internal static readonly IList<Entry> _listCache;
        static InnerCache() {
            List<Entry> tmp  = new List<Entry>();
            //Add items to the list _listCache from XML file
            _listCache = new ReadOnlyCollection<Entry>(tmp);
        }
    }
    protected static IList<Entry> ListCache {
        get {return InnerCache._listCache;}
    }
}

我也会担心有人变异的机会列表 - 可能想使用只读列表!

10k views - that's one every 8 seconds... not sure you need to worry too much... ;-p

But re the code - that is overcomplicating things, and you could still end up initializing it twice. I'd just use a static constructor to do this; it'll be more robust. If you must have full isolated lazy loading (even with other static methods on the type), there is a trick with an inner class to achieve the same:

public class MyClass
{
    static class InnerCache {
        internal static readonly IList<Entry> _listCache;
        static InnerCache() {
            List<Entry> tmp  = new List<Entry>();
            //Add items to the list _listCache from XML file
            _listCache = new ReadOnlyCollection<Entry>(tmp);
        }
    }
    protected static IList<Entry> ListCache {
        get {return InnerCache._listCache;}
    }
}

I would also be concerned about the chance of somebody mutating the list - might want to use a readonly list!

肤浅与狂妄 2024-08-20 05:18:30

没有真正的理由这对你不起作用。但是,如果您想按照示例代码的方式执行此操作,则需要在检查 _listCache 是否为 null 之前锁定。所以你需要一个单独的监视器来锁定。像这样的东西:

public class MyClass
{
        private static object _listCacheMonitor = new object();
        private static List<Entry> _listCache = null; 
        protected static List<Entry> ListCache
        {
            get
            {
                lock (_listCacheMonitor) {    
                    if (_listCache == null)
                    {
                        _listCache = new List<Entry>();
                        //Add items to the list _listCache from XML file
                    }
                }
                return _listCache;
            }
        }
        //....Other methods that work with the list
}

There's not really a reason this wouldn't work for you. However, if you want to do it the way your sample code is, you want to lock before you check to see if _listCache is null. So you would need a separate monitor to lock on. Something like this:

public class MyClass
{
        private static object _listCacheMonitor = new object();
        private static List<Entry> _listCache = null; 
        protected static List<Entry> ListCache
        {
            get
            {
                lock (_listCacheMonitor) {    
                    if (_listCache == null)
                    {
                        _listCache = new List<Entry>();
                        //Add items to the list _listCache from XML file
                    }
                }
                return _listCache;
            }
        }
        //....Other methods that work with the list
}
↘人皮目录ツ 2024-08-20 05:18:30

静态构造函数可能是您最好的选择。静态构造函数在运行时会阻塞所有依赖它的线程,并且它只会运行一次。正如这里的代码所示,锁实际上并没有做任何事情,并且有很多方式可能会发生不好的事情,包括同时从 XML 初始化多个列表。事实上,一个线程可以创建一个新列表,然后锁定并加载一个不同列表,然后返回第三个列表,具体取决于线程切换发生的时间。

A static constructor may be your best bet here. A static constructor will block all threads that depend on it while it's running, and it will only run once. As you have the code here, the lock doesn't really do anything, and there are lots of ways that bad things can happen, including multiple Lists being initialized from XML at the same time. In fact, one thread could create a new List then lock and load a different list and then return a third list, depending on when the thread switching occurs.

绝情姑娘 2024-08-20 05:18:30

多个线程可以初始化_listCache。根据代码生成优化和运行时执行优化,这可能会导致多个线程锁定和更新不同的对象。此外,您不能将列表公开为属性,允许任何人添加/删除带有 oa 锁的对象。

您最好使用不可变列表,多个读者可以在只读模式下安全地解析该列表。或者,您可以使用读写锁,但在初始化控制和访问读写控制之间,事情会变得非常棘手。

Multiple threads can initalize _listCache. Depending on the code generation optimizations and runtime execution optimization, this may result in multiple threads locking and updating different objects. And besides, you can't expose the list as a property allowing anyone to adds/remove object w/o a lock.

You'd be better using an immutable list that multiple readers can safely parse in read-only mode. Alternatively you can use a Read-Write lock, but things will get pretty hairy, between the initialization control and the access r-w control.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文