标签:机制 on() zed 延迟加载 基础 初始 多线程 volatil 检测
目录
public class Singleton {
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
饿汉式单例,在类第一次加载的时候,单例就完成了初始化,是线程安全的。
public class Singleton {
private static Singleton instance = null;
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
懒汉式单例,运用了延迟加载,在需要的时候进行初始化。
但多线程下有两个问题:
怎样修改懒汉式单例才能保证线程安全性呢?
DCL 即双重检查锁定机制
// 尝试一:锁可以保证线程安全性,但并发的情况下阻塞会导致效率低
public class Singleton {
private static Singleton instance = null;
synchronized public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
// 尝试二:缩小同步块的范围,有助于提高效率,但效果微乎其微
public class Singleton {
private static Singleton instance = null;
public static Singleton getInstance() {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
return instance;
}
}
// 尝试三:继续缩小同步块的范围,效率明显提升,但得到的可能不是单例
public class Singleton {
private static Singleton instance = null;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
instance = new Singleton();
}
}
return instance;
}
}
// 尝试四:DCL,第一次空值检测对提升性能起到了很大的作用,但可能得到一个尚未初始化完全的对象
public class Singleton {
private static Singleton instance = null;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
// 尝试五:在 DCL 基础上,为变量 instance 加上 voltile 关键字
public class Singleton {
private volatile static Singleton instance = null;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
voltile 禁止了指令级并行的《重排序》,保证了初始化安全性。
懒汉式单例,使用 DCL + volatile,才具有线程安全性。
public class Singleton {
private static class Holder{
private static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return Holder.instance;
}
}
调用 getInstance 方法导致 Holder 类被加载,加载过程中初始化了单例。
而类的加载是加锁的,加载完成后才能加载另一个类,因此能够保证单例模式的安全性。
同时具有延时加载的特性。
标签:机制 on() zed 延迟加载 基础 初始 多线程 volatil 检测
原文地址:https://www.cnblogs.com/xmsx/p/9752595.html