2018-06-09 孙小北

设计模式之单例模式(C#实现)

养浩然之气,做博学之人

一、简单懒汉模式、线程不安全

/// <summary>    
/// 单例模式--简单懒汉模式    
/// </summary>    
public class DemoSingletonPattern    { 
    //定义一个静态变量来保存类的实例
    private static DemoSingletonPattern instance;
    //定义私有构造函数,使外界不能创建实例
    private DemoSingletonPattern() { }
    //定义公有方法(公有属性)提供一个全局访问点
    public static DemoSingletonPattern GetDemoInstance() { 
        //判断是否已经创建实例,如果已经创建则返回已存在的实例,否则创建新实例 
        if (instance == null) { 
            instance = new DemoSingletonPattern();
        }
        return instance;
    }
    //Demo  获取返回DemoSingletonPattern信息 
    public string GetMessage(){ 
        return "DemoSingletonPattern";
    }
}

二、改进懒汉模式、线程安全

/// <summary>    
/// 单例模式-简单懒汉模式优化,支持多线程安全,开销增加,不推荐 
/// </summary> 
public class DemoLockSingletonPattern    {
    //定义一个静态变量来保存类的实例
    private static DemoLockSingletonPattern instance;
    //定义私有构造函数,使外界不能创建实例
    private DemoLockSingletonPattern() { }
    //定义一个标识确保线程同步
    private static readonly object locker = new object();
    //定义公有方法(公有属性)提供一个全局访问点
    public static DemoLockSingletonPattern GetDemoLockInstance() {
        // 当第一个线程运行到这里时,此时会对locker对象 "加锁",
        // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
        // lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
        lock (locker)
        {   
            // 如果类的实例不存在则创建,否则直接返回
            if (instance == null) 
            { 
                instance = new DemoLockSingletonPattern(); 
            } 
        } 
        return instance;
    }
    //Demo  获取返回DemoLockSingletonPattern信息 
    public  string GetMessage() {
        return "DemoLockSingletonPattern";
    }
}

注意这里我们使用的是新建一个private的object实例padlock来实现锁操作,而不是直接对Singleton进行上锁。直接对类型上锁会出现潜在的风险,因为这个类型是public的,所以理论上它会在任何code里调用,直接对它上锁会导致性能问题,甚至会出现死锁情况。

Note: C#中,同一个线程是可以对一个object进行多次上锁的,但是不同线程之间如果同时上锁,就可能会出现线程等待,或者严重的会出现死锁情况。因此,我们在使用lock时,尽量选择类中的私有变量上锁,这样可以避免上述情况发生。

三、双重检验锁

/// <summary> 
/// 单例模式-懒汉模式--双重检验
/// </summary>
public class DemoTwoLockSingletonPattern    {
    //定义一个静态变量来保存类的实例
    private static DemoTwoLockSingletonPattern instance;
    //定义私有构造函数,使外界不能创建实例
    private DemoTwoLockSingletonPattern() { } 
    //定义一个标识确保线程同步 
    private static readonly object locker = new object(); 
    //定义公有方法(公有属性)提供一个全局访问点
    public static DemoTwoLockSingletonPattern GetDemoTwoLockInstance(){
        // 当第一个线程运行到这里时,此时会对locker对象 "加锁",
        // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
        // lock语句运行完之后(即线程运行完之后)会对该对象"解锁" 
        // 校验是否已经存在实例
        if (instance == null){ 
            lock (locker){ 
                // 如果类的实例不存在则创建,否则直接返回
                if (instance == null){ 
                    instance = new DemoTwoLockSingletonPattern();
                }
            }
        }
        return instance;
    }
    //Demo  获取返回DemoTwoLockSingletonPattern信息
    public  string GetMessage(){
        return "DemoTwoLockSingletonPattern";
    }
}

四、内部类模式

/// <summary>
/// 静态内部类单例模式,线程安全
/// </summary> 
public class DemoInnerSingletonPattern {
    //内部类InnerSingletonPatternHandler只有在GetInnerSingletonPatternInstance()方法第一次调用的时候才会被加载(实现了延迟加载效果),
    //而且其加载过程是线程安全的(实现线程安全)。内部类加载的时候只实例化了一次instance
    private static class InnerSingletonPatternHandler{ 
    /// <summary> 
    /// 当一个类有静态构造函数时,它的静态成员变量不会被beforefieldinit修饰
    /// 就会确保在被引用的时候才会实例化,而不是程序启动的时候实例化 
    /// </summary>
    static InnerSingletonPatternHandler() { }
        internal static DemoInnerSingletonPattern instance = new DemoInnerSingletonPattern();
    }        
    //定义私有构造函数,使外界不能创建实例
    private DemoInnerSingletonPattern() { }
    public static DemoInnerSingletonPattern GetInnerSingletonPatternInstance(){ 
        return InnerSingletonPatternHandler.instance;
    }
    //Demo  获取返回DemoInnerSingletonPattern信息
    public string GetMessage(){ 
        return "DemoInnerSingletonPattern";
    }
}

五、饿汉模式

/// <summary>
/// 单例模式-饿汉模式 
/// </summary>
public class DemoHungrySingletonPattern{ 
////定义一个静态变量来保存类的实例
    private static DemoHungrySingletonPattern instance = new DemoHungrySingletonPattern();
    //定义私有构造函数,使外界不能创建实例 
    private DemoHungrySingletonPattern() { }
    public static DemoHungrySingletonPattern GetDemoHungrySingletonInstance() { 
        return instance;
    } 
    //Demo  获取返回DemoHungrySingletonPattern信息
    public string GetMessage(){
        return "DemoHungrySingletonPattern";
    }
}

编辑:孙小北

本文地址: https://www.xiaowangyun.com/wyblog/detail/?id=187

版权归属: www.xiaowangyun.com   转载时请以链接形式注明出处

0 条评论

快来评论

物以类聚

最新评论

2017-10-06

一辈子不长,只有珍惜了,才不至于后悔。

2017-10-06

懂得感恩,才能走得更远。

标签云

归档

取消

感谢您的支持,您的每一次打赏都是一次鼓励!

扫码支持
每一次支持,都是不懈的动力

打开支付宝扫一扫,即可进行扫码打赏哦