【发布时间】:2012-06-04 21:00:47
【问题描述】:
据我所知volatile write happens-before volatile read,所以我们总是会在 volatile 变量中看到最新的数据。我的问题主要涉及 happens-before 这个词,它发生在哪里?我写了一段代码来澄清我的问题。
class Test {
volatile int a;
public static void main(String ... args) {
final Test t = new Test();
new Thread(new Runnable(){
@Override
public void run() {
Thread.sleep(3000);
t.a = 10;
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
System.out.println("Value " + t.a);
}
}).start();
}
}
(为清楚起见省略了 try catch 块)
在这种情况下,我总是在控制台上看到要打印的值 0。如果没有Thread.sleep(3000);,我总是看到值 10。这是发生在关系之前的情况,还是打印“值 10”,因为线程 1 更早地启动了线程 2?
很高兴看到每个程序启动时带有和不带有 volatile 变量的代码的行为都不同的示例,因为上面代码的结果仅取决于(至少在我的情况下)线程的顺序和线程睡觉。
【问题讨论】:
-
我在这里可能错了,但 AFAIK volatile 关键字本质上告诉 JVM,它不能对变量的访问顺序进行任何更改,以尝试优化。换句话说,您以潜在的等待为代价获得了安全性(如串行执行)。我可能是错的,所以看看其他人对此事的看法会很有趣。
-
唯一的 volatile 保证是任何读取变量的线程都会看到最近写入的值。 volatile修饰符主要用于多线程。 Java 允许线程可以保留共享变量(缓存)的私有工作副本。这些工作副本需要使用主存储器中的主副本进行更新。易失性意味着变量将仅存在于主内存中,而不存在于私有工作副本(缓存)中。
标签: java concurrency volatile