zoukankan      html  css  js  c++  java
  • .NET下的延迟加载

    在应用中有很多实例可能需要延迟创建对象, 比如设计模式中的单例模式就是一种非常常见的情况.如果不考虑线程安全我们通常会编写如下代码:

    public class SingleInstance
    {
        private static SingleInstance instance;
        private SingleInstance()
        {   
        }
        
        public static SingleInstance Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new SingleInstance();
                }
                
                return instance;
            }
        }
    }
    

    如果我们想让其可以在多线程环境下运行, 那么我们升级一下此使用double check的方式去避免线程间创建多个示例. 代码如下:

    public class SingleInstance { private static SingleInstance instance; private static object lockObj = new Object(); private SingleInstance() { } public static SingleInstance Instance { get { if (instance == null) { lock (lockObj) { if (instance == null) { instance = new SingleInstance(); } } } return instance; } } }

    以上代码在并非真的是线程安全了, 因为在IA64CPU架构上,会存在返回null的可能. 所以我们使用关键字volatile来修饰一下instance对象(volatile的作用就是添加内存栅栏fence), 代码就变成了

    public class SingleInstance
    {
        private static volatile SingleInstance instance;
        private static object lockObj = new Object();
        private SingleInstance()
        {   
        }
        
        public static SingleInstance Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (lockObj)
                    {
                        if (instance == null)
                        {
                            instance = new SingleInstance();
                        }
                    }
                }
                
                return instance;
            }
        }
    }

    看上去挺不错的了. 就是代码有点长了, .NET为我们提供了Lazy对象为我们解决了创建此类对象的机制. 修改后代码如下:

    public class SingleInstance
    {   
        private static Lazy<SingleInstance> SingleInstanceFacotry = new Lazy<SingleInstance>(()=> new SingleInstance(), true);   
        
        private SingleInstance()
        {   
        }
        
        public static SingleInstance Instance
        {
            get
            {
                return SingleInstanceFacotry.Value;
            }
        }
    }

    Lazy的构造函数中可以方便的设置是否需要线程安全.

    这样每次都要有个Lazy来辅助, .NETBCL的设计者还提供了另外一种模式, 使用LazyInitializer来保证线程是安全的.示例代码如下:

    public class SingleInstance
    {   
        private static SingleInstance instance;
        
        private SingleInstance()
        {   
        }
        
        public static SingleInstance Instance
        {
            get
            {
                LazyInitializer.EnsureInitialized(ref instance, ()=> new SingleInstance());
                return instance;
            }
        }
    }

    这种方式的好处是, 你在原来的非线程安全重构到线程安全更新的代码最少.

  • 相关阅读:
    VS2015调试ArcMap Add-in插件提示尝试运行项目时出错,无法启动程序“路径arcmap.exe”
    c#重命名文件,报错“System.NotSupportedException”类型的未经处理的异常在 mscorlib.dll 中发生”
    C# string contains 不区分大小写
    CSS div 高度满屏
    ArcGIS Server SOE开发之奇怪异常:
    C# 读取XML注释
    .Net程序员之不学Java做安卓开发:奇怪的Java语法
    .Net程序员之不学Java做安卓开发:Android Studio中的即时调试窗口
    JS去遍历Table的所有单元格中的内容
    判断 checkbox 是否选中以及 设置checkbox选中
  • 原文地址:https://www.cnblogs.com/cuiweifu/p/3786466.html
Copyright © 2011-2022 走看看