关于多线程下的双重检测模式

来源:9-5 jmm的内存可见性

幕布斯9391928

2019-12-26

在单例的双重检测模式下,都为代码块增加synchronized修饰了,此时已经是一个单线程下的操作了,即使发生了指令重排,但是结果不是依然是对的吗?

写回答

2回答

翔仔

2019-12-27

new操作会经历三个过程

  1. 分配内存

  2. 执行Singleton构造函数

  3. 将实例指向分配的内存

由于是synchronized修饰的,所以不保证操作的顺序,只保证原子性

如果按照1->3->2去执行的话,当线程A执行完3的时候,instance是有值了,但是还没执行Singleton构造函数初始化实例,然后线程B在synchronized外面的if判断时,由于instance非空,所以直接返回,获取到一个没有实例化完成的对象,可以细细体会一下

2
3
翔仔
回复
慕勒2150035
同学好,已经回复了哈
2020-04-03
共3条回复

翔仔

2020-04-03

同学好,对着代码说好点。。

public class Singleton {

    private static Singleton instance;

    private Singleton(){}

    public static Singleton getInstance(){

        //第一次检测
        if (instance==null){
            //同步
            synchronized (Singleton.class){
                if (instance == null){
                    //多线程环境下可能会出现问题的地方
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

1)instance并没有被锁呀,虽然A在执行1 3 2 的时候锁没被释放,但是instance已经在执行3即分配内存空间但是没有创建完成的时候就有值了。。B此时去用的时候,在第一个if里就能获取到instance有值的反馈,就不会去执行sync里面的逻辑了,而是直接将不完整的实例给返回。

2)还是第一个问题,你要明确锁的是啥,锁的只是Singleton这个Class对象,没锁它的实例呀。。

0
0

剑指Java面试-Offer直通车 百度资深面试官授课

招聘季即将到来,让百度资深面试官来为你的高薪Offer保驾护航

8427 学习 · 1870 问题

查看课程