请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

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

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

正在回答

2回答

new操作会经历三个过程

  1. 分配内存

  2. 执行Singleton构造函数

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

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

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

2 回复 有任何疑惑可以回复我~
  • 提问者 幕布斯9391928 #1
    非常感谢!
    回复 有任何疑惑可以回复我~ 2019-12-27 14:52:54
  • 老师,我还有些地方没想明白。
    1)这里的意思是按照1->3->2去执行的话,当线程A执行完3的时候,CPU给B占用了么?那这时线程A还没执行完,类锁还没有释放的,instance也是一个类变量,为什么可以说线程B在synchronized外面的if判断的?
    3)如果这里线程B还能读取instance,说明synchronized是类似我们数据库中讲的共享锁么?就是事务还没执行完成就可以读取中间数据,所以读到了instance为null直接返回导致的出错呢?
    回复 有任何疑惑可以回复我~ 2020-04-02 21:24:37
  • 翔仔 回复 慕勒2150035 #3
    同学好,已经回复了哈
    回复 有任何疑惑可以回复我~ 2020-04-03 02:05:29
翔仔 2020-04-03 02:05:15

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

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 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信