java - 关于“双重检查锁定”的另一个问题
问题描述
我已经根据“有效的 java”#83 修改了一个“正常”的 DCL 单例案例,如下所示。
import java.util.Date;
public class MySystem {
private Date date = new Date();
private MySystem() {};
private static volatile MySystem instance;
public Date getDate() {
return date;
}
public static MySystem getInstance() {
MySystem my = instance;
if (my == null) {
synchronized (MySystem.class) {
if (instance == null) {
instance = my = new MySystem();
}
}
}
return my;
}
}
但是当我运行它时,NullpointerException 会以非常高的比例被抛出。当我如下修改它时,一切正常。为什么?
import java.util.Date;
public class MySystem {
private Date date = new Date();
private MySystem() {};
private static volatile MySystem instance;
public Date getDate() {
return date;
}
public static MySystem getInstance() {
MySystem my = instance;
if (my == null) {
synchronized (MySystem.class) {
my = instance;
if (my == null) {
instance = my = new MySystem();
}
}
}
return my;
}
}
主要如下。很难弄清楚其中的区别。
public class Main {
public static void main(String[] args) {
new Thread() {
public void run() {
System.out.println(MySystem.getInstance().getDate());
}
}.start();
new Thread() {
public void run() {
System.out.println(MySystem.getInstance().getDate());
}
}.start();
}
}
解决方案
不同之处在于这一行:
my = instance;
您正在将两个对象引用都放在 JVM 堆上的一个位置。之后你打电话:
my = new MySystem();
这使得两者my
都不是instance
空的(你不能链接=
运算符,所以只有my
实例化)。然后在调用这个之后:
MySystem.getInstance().getDate()
您没有在 null 上调用方法。
当它同步时,第二个线程正在等待my
(为了调用此行my = instance
)的实例化并且没有获得 NPE。
推荐阅读
- javascript - 数组的索引?
- asp.net-mvc - 我无法在 IIS 的虚拟目录中显示/浏览我的图像
- python - Python,tensorflow没有属性graphdef和cudart64_101.dll没有找到
- javascript - 如何将一个固定长宽比的 div 和一个固定宽度的 div 放在一起?
- java - 在 tomcat 中设置 max-threads = 0 不应接受用户的任何进一步请求,但它正在接受。为什么?
- delphi - Delphi7如何安装Tntcontrols
- python - 如果找到湮灭对,Django ORM 排除结果
- angular - 如何将本地存储值存储在
在角度 6? - spring-boot - 使用定义的字符串变量按键缓存
- undefined - 为什么在浏览器中显示订阅未定义