单例模式:Singleton Pattern

定义

保证一个类仅有一个实例,并提供一个访问它的全局访问点

适用条件

当系统需要某个类只能有一个实例时适用

大致有六种写法,每一种写法各有特点:

  1. 懒汉 – 线程不安全
     这种写法可以实现lazy-loading, 但是多个线程可能会同时申请实例,无法保证安全。
  2. 懒汉 – 线程安全
     在1的基础上增加一个同步锁synchronized, 以保证线程安全;
     但是效率不高,因为事实上只需要在第一次实例化的时候需要同步锁,以后就不可能再实例化了。
  3. 懒汉 – 线程安全 – 双检锁(DCL)
     双检锁的奇妙之处在于,只在第一次实例化的时候才会进入第一层锁,以后就不可能进入第一次锁了;
     这样多个线程进入第二层锁也只会在第一次。这就解决了第2种写法效率低下的问题。
  4. 懒汉 – 线程安全 – 静态内部类
     这种方式能达到双检锁同样的效果,但是只在静态域延迟初始化的情况下才适用。
  5. 饿汉 – 线程安全
     线程安全,但是不能实现lazy-loading。
  6. 饿汉 – 线程安全 – 枚举
      最简洁的一种实现方法,不过其中的奥妙全自动需要追溯到枚举的实现上,感兴趣的读者可查阅其他资料,这里不作赘述。
     自动支持序列化,但是不能实现lazy-loading。

类图

这里写图片描述

实现(java)

懒汉 – 线程不安全
public class Singleton {
    private static Singleton instance = null;
    private Singleton() {}

    public static Singleton getInstance() {
        if(instance == null) instance = new Singleton();
        return instance;
    }
}
懒汉 – 线程安全
public class Singleton {
    private static Singleton instance = null;
    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if(instance == null) instance = new Singleton();
        return instance;
    }
}
懒汉 – 线程安全 – 双检锁(DCL)
public class Singleton {
    private static volatile Singleton instance = null;
    private Singleton() {}

    public static Singleton getInstance() {
        if(instance == null) {
            synchronized(Singleton.class) {
                if(instance == null) instance = new Singleton();
            }
        }
        return instance;
    }
}
懒汉 – 线程安全 – 静态内部类
public class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton() {}
    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
饿汉 – 线程安全
public class Singleton {
    private static final Singleton instance = new Singleton();
    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}
饿汉 – 线程安全 – 枚举
public enum Singleton {
    INSTANCE;
    public void solve() { System.out.println("ok"); } 

}

实现(C#)

懒汉 – 线程不安全
class Singleton {
        private static Singleton instance = null;
        private Singleton() { }

        public static Singleton getInstance() {
            if (instance == null) instance = new Singleton();
            return instance;
        }
    }
懒汉 – 线程安全
class Singleton {
        private static Singleton instance = null;
        private static readonly object syncRoot = new object();
        private Singleton() { }

        public static Singleton getInstance() {
            lock (syncRoot) {       //对静态只读进程辅助对象加锁
                if (instance == null) instance = new Singleton();
                return instance;
            } 
        }
    }
懒汉 – 线程安全 – 双检锁(DCL)
class Singleton {
        private static Singleton instance = null;
        private static readonly object syncRoot = new object();
        private Singleton() { }

        public static Singleton getInstance() {
            if (instance == null) {
                lock (syncRoot) {       //对静态只读进程辅助对象加锁
                    if (instance == null) instance = new Singleton();
                } 
            }
            return instance;
        }
    }
懒汉 – 线程安全 – 静态内部类
饿汉 – 线程安全
饿汉 – 线程安全 – 枚举

实现(C++)

懒汉 – 线程不安全
懒汉 – 线程安全
懒汉 – 线程安全 – 双检锁(DCL)
懒汉 – 线程安全 – 静态内部类
饿汉 – 线程安全
饿汉 – 线程安全 – 枚举

应用

不推荐使用 1 和 2
在不要求lazy-loading的情况下,推荐 5 (3 也可)
在要求lazy-loading的情况下,推荐 4 (3 也可)
涉及反序列化创建对像时,推荐 6
3 的性价比最高,万金油

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值