Согласно Спецификации языка Java (Пример 17.4 -1) следующий фрагмент (начиная с A == B == 0
)...
Thread 1 Thread 2
-------- --------
r2 = A; r1 = B;
B = 1; A = 2;
... может привести к r2 == 2
и r1 == 1
. Это связано с тем, что результат выполнения B = 1;
не зависит от того, было ли выполнено r2 = A
, поэтому JVM может свободно менять порядок выполнения этих двух инструкций. Другими словами, спецификация допускает следующее чередование:
Thread 1 Thread 2
-------- --------
B = 1;
r1 = B;
A = 2;
r2 = A;
что явно приводит к r2 == 1
и r1 == 1
.
Мой вопрос:
Предположим, мы немного подправим пример:
Thread 1 Thread 2
-------- --------
r2 = A; r1 = B;
monitorenter obj monitorenter obj
monitorexit obj monitorexit obj
B = 1; A = 2;
где obj
— ссылка, совместно используемая потоками.
Разрешено ли изменение порядка r2 = A
и B = 1
?
JLS говорит...
Однако компиляторам разрешено переупорядочивать инструкции в любом потоке, если это не влияет на выполнение этого потока в отдельности.
...что указывает на то, что инструкции могут поменять местами. С другой стороны, следующее утверждение
Разблокировка монитора происходит перед каждой последующей блокировкой этого монитора.
указывает, что при определенных планировках у нас может быть отношение «происходит до» между операторами в двух потоках, что предположительно запрещает изменение порядка инструкций.