Зі сторінки 291 іспитів із практики програмістів OCP Java SE 6, питання 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
, але ... - Бум, планувальник вибирає другий потік для запуску.
- Отже, входить друга нитка
run()
. Статичнийid
нерухомий1
, тому він виконує методpick()
.P Q
друкується. - Планувальник вибирає перший потік для запуску. Він бере
0
з його стека і зберігає до статичногоid
. Отже, перший потік також виконуєтьсяpick()
і друкуєтьсяP Q
.
Однак у книзі написано, що ця відповідь неправильна:
Це неправильно, оскільки рядок
id = 1 - id
міняє значенняid
між0
і1
. Немає шансів, щоб один і той же метод був виконаний двічі.
Я не згоден. Я думаю, що є певний шанс для сценарію, який я представив вище. Такий своп не є атомним. Я помиляюся?