这是一些关于volatile的一些细节的旁注说明。在这里写这是因为它是太多的评论。我想给出一些示例,显示易变性如何影响可见性,以及在jdk 1.5中如何改变。
给出以下示例代码:
public class MyClass
{
private int _n;
private volatile int _volN;
public void setN(int i) {
_n = i;
}
public void setVolN(int i) {
_volN = i;
}
public int getN() {
return _n;
}
public int getVolN() {
return _volN;
}
public static void main() {
final MyClass mc = new MyClass();
Thread t1 = new Thread() {
public void run() {
mc.setN(5);
mc.setVolN(5);
}
};
Thread t2 = new Thread() {
public void run() {
int volN = mc.getVolN();
int n = mc.getN();
System.out.println("Read: " + volN + ", " + n);
}
};
t1.start();
t2.start();
}
}
这个测试代码的行为在jdk1.5中有很好的定义,但是在jdk1.5之前没有很好的定义。
在前jdk1.5世界中,易失性访问和非易失性访问之间没有定义的关系。因此,该程序的输出可以是:
>读:0,0
>阅读:0,5
>阅读:5,0
>阅读:5,5
在jdk1.5世界中,易变性的语义被改变,使得易失性访问以与同步完全相同的方式影响非易失性访问。因此,在jdk1.5世界中只有某些输出是可能的:
>读:0,0
>阅读:0,5
>读:5,0< - 不可能
>阅读:5,5
输出3.是不可能的,因为从volatile _volN读取“5”在两个线程之间建立一个同步点,这意味着在分配到_volN之前从t1获得的所有动作必须在t2可见。
进一步阅读: