先看代码
import java.util.concurrent.CountDownLatch;
public class Disorder {
private static int x = 0, y = 0;
private static int a = 0, b = 0;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < Long.MAX_VALUE ; i++) {
x = 0;
y = 0;
a = 0;
b = 0;
CountDownLatch latch = new CountDownLatch(2);
Thread one = new Thread(new Runnable() {
@Override
public void run() {
a = 1;
x = b;
latch.countDown();
}
});
Thread two = new Thread(new Runnable() {
@Override
public void run() {
b = 1;
y = a;
latch.countDown();
}
});
one.start();
two.start();
latch.await();
String result = "第" + i + "次(" + x + "," + y + ")";
if (x == 0 && y == 0) {
System.err.print(result);
break;
}
}
}
}
程序创建两个线程,分别做对私有静态变量 a b x y 做
a = 1
x = b
和
b = 1
y = a
的操作
如果遇到 x == 0 且 y == 0 ,打印循环次数,程序停止
而设定的这种终止条件,只有 x = b 和 y = a 同时先执行的情况下才会成立
乱序存在的条件, as - if - serial,结果不影响单线程的最终一致性
如何避免乱序执行?
底层方面,CPU中有 屏障指令 ,被屏障指令隔开的指令段之间有严格的先后顺序
Intel的屏障指令为 lfense sfense mfense,l = load(读), s = save(写), m = l & s
Java方面,对JVM有规定,JVM需要实现几个规范
LoadLoadBarrier, LoadStoreBarrier, StoreLoadBarrier, StoreStoreBarrier
最后体现在代码上,就是对变量使用 volatile 修饰符