【发布时间】:2012-10-11 12:05:15
【问题描述】:
java并发教程指出:
对于引用变量和大多数原始变量(除了 long 和 double 之外的所有类型),读取和写入都是原子的。
对于声明为 volatile 的所有变量(包括 long 和 double 变量),读写都是原子的。
我创建了一个简单的实验来测试这个
package experiment0;
public class Experiment0 {
public static int i=9;
public static void main(String[] args) {
i=9;
(new Thread(){
public void run(){
while(i==9){
//System.out.println("i==9");
}
System.out.println("\ni!=9");
}
}).start();
(new Thread(){
public void run(){
try{
Thread.sleep(3000);
i=8;
}catch(Exception e){
}
}
}).start();
}
}
当我运行这段代码时,程序永远不会被终止!为了让它工作,我要么取消注释第一个线程的while循环内的行,要么将i声明为volatile。
我错过了什么吗?文档是否错误,是否应该说在这种情况下所有原语都应声明为易失性?为什么写信给System.out“解决”了问题?是否给第二个线程足够的时间来更改i?
【问题讨论】:
-
在我的情况下两者都很好..
-
您引用的手册部分与您的代码存在的问题并不真正相关。 “原子”写入并不意味着另一个线程将看到这些更改。要更详细地探索这一点,您可以做的一件事是查看编译器是否优化了读取,这就是您看不到更新的原因。
-
原子意味着更新是不可分割的。您永远不会看到中间状态,只会看到旧值或新值。如果您只看到旧值,它仍然是原子的。
-
有关为什么写入 System.out 可以解决问题的说明,请参阅Loop doesn't see changed value without a print statement。
标签: java multithreading concurrency atomic volatile