【问题标题】:C# Static Property LockingC# 静态属性锁定
【发布时间】:2009-12-03 21:32:43
【问题描述】:

只是寻找此代码的代码审查。 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
}

【问题讨论】:

    标签: c# asp.net .net-2.0


    【解决方案1】:

    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;}
        }
    }
    

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

    【讨论】:

    • +1。有点迂腐:10k 次观看 - 平均每 8 秒一次。根据墨菲定律,前两个将同时发生。
    • 或者只是在Application_Start事件中初始化
    • 换句话说,如果发生碰撞的概率不为 0,那么它就在 1 附近。
    【解决方案2】:

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

    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
    }
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 实际上,现在我再看一遍,它甚至可以加载与锁定的列表不同的列表,如果加载发生在静态变量上,它可以将不同的部分加载到多个列表!
      【解决方案4】:

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

      您最好使用一个不可变的列表,多个阅读器可以在只读模式下安全地解析。或者,您可以使用读写锁,但在初始化控件和访问 r-w 控件之间会变得很麻烦。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-25
        • 2014-09-10
        • 2010-10-30
        相关资源
        最近更新 更多