有人可以帮我理解为什么以下程序退出? 一个线程用1和2替换i。 另一个线程正在读取i,如果i值既不是1也不是2,它将退出。 实际上下面的程序不应该退出,但它会退出打印1或2。
static volatile int i = 1;
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
i = (i == 1 ? 2 : 1);
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if (i != 1 && i != 2) {
System.out.println("i=" + i);
System.exit(0);
}
}
}
}).start();
}
答案 0 :(得分:3)
因为在if (i != 1 && i != 2)
语句中有两条检查指令,它们是按顺序计算的,因此有可能在调用i != 1
时,i
的值为2
所以它评估为false
,并且在调用i != 2
时,i
已被切换线程切换回值1
,因此它也评估为false
因此,整个if (i != 1 && i != 2)
评估为false,因为java中if
的评估不是原子的。
答案 1 :(得分:2)
让我们假设你在if (i != 1 && i != 2)
。有两个单独的行动:
read i and compare to 1
read i and compare to 2
由于i
是易失性的,因此编译器/ VM需要从内存中拉两次。有一种情况:(1)读取2
和(2)读取1
。在这种情况下,您将进入System.exit
。