双重锁检查
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
}
}