java 多线程 双重锁检查

双重锁检查

public class User {
    
    private static User user;
    
    public static User getInstance() {
        if (user == null) { // 1:第一次检查
            synchronized (User.class) { // 2:加锁
                if (user == null) { // 3:第二次检查
                    user = new User(); //4
                }
            }
        }
        return user; // 10
    }
}

上面的代码是一个简单的单例模式  ,但是这个代码是有问题的  问题在于第4步

java 创建一个对象需要

  1:分配对象的内存空间
  2:初始化对象
  3:设置对象指向刚分配的内存地址

但是处理器可能会"重排序" 为

    1:分配对象的内存空间
  3:设置对象指向刚分配的内存地址

    2:初始化对象

如果线程A 进入 getInstance() 然后 进入syn 然后new User();new User 被重排序,当运行到设置对象内存地址时 ,  线程B 进入 getInstance() 判断 user不为null 返回user 此时线程A 还没有完成初始化对象 而线程B已经返回了 user 所以 会有问题。

如果解决呢  可以用 volatil 关键字解决 : volatile 具有可见性 用volatile修饰的变量 一个线程修改后立刻对所有线程可见。

public class User {
    private volatile  static User user; // 加 volatile 解决问题
    public static User getInstance() {
        if (user == null) { // 1:第一次检查
            synchronized (User.class) { // 2:加锁
                if (user == null) { // 3:第二次检查
                    user = new User(); //4
                }
            }
        }
        return user; // 10
    }
}

猜你喜欢

转载自blog.csdn.net/qq_25825923/article/details/82666752