id = 1 - id 是原子的吗?
摘自 OCP Java SE 6 Programmer Practice Exams 第 291 页,问题 25:
public class Stone implements Runnable {
static int id = 1;
public void run() {
id = 1 - id;
if (id == 0)
pick();
else
release();
}
private static synchronized void pick() {
System.out.print("P ");
System.out.print("Q ");
}
private synchronized void release() {
System.out.print("R ");
System.out.print("S ");
}
public static void main(String[] args) {
Stone st = new Stone();
new Thread(st).start();
new Thread(st).start();
}
}
其中一个答案是:
输出可以是
P Q P Q
我将此答案标记为正确。我的理由:
- 我们将启动两个线程。
- 第一个进入 .
run()
- 根据 JLS 15.26.1,它首先评估 。结果是 。它存储在线程的堆栈上。我们正要将其保存为静态 ,但是...
1 - id
0
0
id
- Boom,调度程序选择要运行的第二个线程。
- 因此,第二个线程进入 。静态是静止的,所以他执行方法。 已打印。
run()
id
1
pick()
P Q
- 调度程序选择要运行的第一个线程。它从其堆栈中获取并保存到静态 。因此,第一个线程也会执行并打印 。
0
id
pick()
P Q
然而,在书中写道,这个答案是不正确的:
这是不正确的,因为该行交换了 和 之间的值。同一方法不可能执行两次。
id = 1 - id
id
0
1
我不同意。我认为我上面介绍的场景有一些机会。这种交换不是原子的。我错了吗?