这可以通过例子来证明
不断切换两个字段,一个标记为易失性,另一个不在所有置位和所有位清零之间切换
读取另一个线程上的字段值
看到可以以不一致的状态读取foo字段(未使用volatile保护的字段),这在使用volatile保护的bar字段中永远不会发生
码
public class VolatileTest {
private long foo;
private volatile long bar;
private static final long A = 0xffffffffffffffffl;
private static final long B = 0;
private int clock;
public VolatileTest() {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
foo = clock % 2 == 0 ? A : B;
bar = clock % 2 == 0 ? A : B;
clock++;
}
}
}).start();
while (true) {
long fooRead = foo;
if (fooRead != A && fooRead != B) {
System.err.println("foo incomplete write " + Long.toHexString(fooRead));
}
long barRead = bar;
if (barRead != A && barRead != B) {
System.err.println("bar incomplete write " + Long.toHexString(barRead));
}
}
}
public static void main(String[] args) {
new VolatileTest();
}
}
输出量
foo incomplete write ffffffff00000000
foo incomplete write ffffffff00000000
foo incomplete write ffffffff
foo incomplete write ffffffff00000000
请注意,这仅对我而言是在32位VM上运行时发生的,在64位VM上,我在几分钟内没有收到任何错误。