【发布时间】:2021-07-04 14:56:59
【问题描述】:
我使用 jdk1.8。我认为没有 volatile 的双重检查锁是正确的。 我多次使用 countdownlatch 测试,对象是单例的。 如何证明它一定需要“volatile”?
更新 1
抱歉,我的代码没有格式化,因为我无法接收一些 JavaScript 公共类 DCLTest {
private static /*volatile*/ Singleton instance = null;
static class Singleton {
public String name;
public Singleton(String name) {
try {
//We can delete this sentence, just to simulate various situations
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.name = name;
}
}
public static Singleton getInstance() {
if (null == instance) {
synchronized (Singleton.class) {
if (null == instance) {
instance = new Singleton(Thread.currentThread().getName());
}
}
}
return instance;
}
public static void test() throws InterruptedException {
int count = 1;
while (true){
int size = 5000;
final String[] strs = new String[size];
final CountDownLatch countDownLatch = new CountDownLatch(1);
for (int i = 0; i < size; i++) {
final int index = i;
new Thread(()->{
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
Singleton instance = getInstance();
strs[index] = instance.name;
}).start();
}
Thread.sleep(100);
countDownLatch.countDown();
Thread.sleep(1000);
for (int i = 0; i < size-1; i++) {
if(!(strs[i].equals(strs[i+1]))){
System.out.println("i = " + strs[i] + ",i+1 = "+strs[i+1]);
System.out.println("need volatile");
return;
}
}
System.out.println(count++ + " times");
}
}
public static void main(String[] args) throws InterruptedException {
test();
}
}
【问题讨论】:
-
邮政编码,这样我们可以更好地提供帮助
-
网上有大量关于双重检查锁范式的资料。这是一个例子:cs.cornell.edu/courses/cs6120/2019fa/blog/…
-
好的。如何证明。例如,想象一下,对象变量赋值和新对象初始化是独立的动作(没有原子性)。它有时可能会导致多线程环境中的不一致。此外,Java 使用缓存,在双重检查方法的情况下需要显式禁用。第一次检查发生在同步之外。
-
@AlexanderAlexandrov 你到底在说什么“缓存”?它是a lot more complicated then you over-simplify it
-
这里解释一下volatile关键字stackabuse.com/concurrency-in-java-the-volatile-keyword上下文中的缓存
标签: java concurrency singleton volatile double-checked-locking