什么是双端检索机制?

194 阅读1分钟

public class SingletonDemo {

public static SingletonDemo instance = null;


private SingletonDemo() {
    System.out.println("我是构造方法");
}

private static  SingletonDemo getInstance() {
    if (instance == null) {
        synchronized (SingletonDemo.class) {
           if (instance==null){
               instance = new SingletonDemo();
           }
        }
    }
    return instance;
}

public static void main(String[] args) {
    ExecutorService executorService = Executors.newFixedThreadPool(10);
    for (int i = 0; i < 10; i++) {
        executorService.submit(() -> {
            instance =  SingletonDemo.getInstance();
        });
    }
    executorService.shutdown();
}

双端检索机制的隐患 从上面的结果我们可以看出来,好像加了双端检索机制貌似就没有出现问题啦, 而且运行检验的时候,他的确是只输出了一次构造方法吗? 但是问题真的就这么解决了吗?

DCL(双端检索机制)机制不一定安全,因为有指令重排的存在,加入voliate则可以禁止指令重排 原因是在某个线程执行到第一次检测,读取到instance为null的时候,instance对象没有完成对象的初始化,而 instance = new SingletonDemo();又可以分为三步 memory = allocate() 分配内存空间 语句1 instance(memory ) 初始化对象 语句2 instance = memory 实例指向内空间 语句3 因为语句2和语句3没有数据依赖性,所以 他们的顺序可以指令重排, 如果为132顺序的话.在对象还没有完成对象的初始化的时候,直接把null的对象指向内存空间,会导致出现null的结果

解决双端检索机制的隐患

public static volatile SingletonDemo instance = null;


private SingletonDemo() {
    System.out.println("我是构造方法");
}

private static  SingletonDemo getInstance() {
    if (instance == null) {
        synchronized (SingletonDemo.class) {
           if (instance==null){
               instance = new SingletonDemo();
           }
        }
    }
    return instance;
}

public static void main(String[] args) {
    ExecutorService executorService = Executors.newFixedThreadPool(10);
    for (int i = 0; i < 10; i++) {
        executorService.submit(() -> {
            instance =  SingletonDemo.getInstance();
        });
    }
    executorService.shutdown();
}