【发布时间】:2019-09-03 11:20:11
【问题描述】:
我知道,in theory,要实现正确的单例,除了双重检查锁定和synchronized,我们应该创建一个实例字段volatile。
但在现实生活中,我无法举出一个例子,这会暴露问题。也许有一个 JVM 标志会禁用某些优化,或者允许运行时进行这种代码排列?
这是代码,据我所知,它应该不时打印到控制台,但它没有:
class Data {
int i;
Data() {
i = Math.abs(new Random().nextInt()) + 1; // Just not 0
}
}
class Keeper {
private Data data;
Data getData() {
if (data == null)
synchronized (this) {
if (data == null)
data = new Data();
}
return data;
}
}
@Test
void foo() throws InterruptedException {
Keeper[] sharedInstance = new Keeper[]{new Keeper()};
Thread t1 = new Thread(() -> {
while (true)
sharedInstance[0] = new Keeper();
});
t1.start();
final Thread t2 = new Thread(() -> {
while (true)
if (sharedInstance[0].getData().i == 0)
System.out.println("GOT IT!!"); // This actually does not happen
});
t2.start();
t1.join();
}
有人可以提供一个代码,清楚地证明所描述的理论上缺乏volatile 问题吗?
【问题讨论】:
标签: java multithreading singleton volatile