Синхронизирует - с эдегами компилятор переупорядочивает барьеры в обоих направлениях?

У меня есть вопрос относительно модели памяти Java. В следующем примере:

action 1
action 2
synchronized(monitorObject) { //acquire
    action 3
} //release
action 4

acquire и release могут быть любыми синхронизациями - с реброми (блокировка, разблокировка, запуск потока, объединение потока, обнаружение прерывания потока, volatile-write, volatile-read и т.д.)

Гарантировано ли, что action 3 невозможно перенести до приобретения и не может быть перемещено после выпуска?

И гарантируется ли, что action 2 не может быть перемещен после приобретения (ни до, ни после релиза), и что action 4 не может быть перемещен до релиза (до и после приобретения)?

Итак, синхронизируются ли с границами "двунаправленные барьеры" для действий по переупорядочению компилятора?


РЕДАКТИРОВАТЬ 1 Меня это беспокоит, потому что если синхронизация - с ребрами не были двунаправленными переупорядочивающими барьерами, то компилятор мог бы просто создать тупик путем перемещения блокировки в другие.

Или двунаправленные переупорядочивающие барьеры, которые даже не нужны для предотвращения этого, потому что блокировка не может быть переброшена в другие, потому что это изменит порядок синхронизации?


РЕДАКТИРОВАТЬ 2 Действия 1, 2, 3 и 4 являются "межпотоковыми действиями", как определено JMM.


РЕДАКТИРОВАТЬ 3 Вот пример, показывающий, как переупорядочение может вызвать тупик:

x и y - общие переменные, а syncA и syncB могут быть получены любым другим потоком. Но с помощью следующего кода невозможно установить тупик.

/* 1 */  synchronized(syncA) {
/* 2 */      x = 1;
/* 3 */  }
/* 4 */  y = 0;
/* 5 */  synchronized(syncB) {
/* 6 */      y = 1;
/* 7 */  }

Если, однако, приобретение syncA переупорядочивается в блок syncB, это может вызвать тупик:

y = 0;
synchronized(syncB) {
    y = 1;
    synchronized(syncA) {
        x = 1;
    }
}

Я думаю, что это не законное преобразование компилятора, потому что это изменит порядок синхронизации. Правильно ли я с этим предположением? Какая часть модели памяти Java (JMM) разрешает/запрещает это?

Ответ 1

Благодаря assylias для ссылки на этот вопрос, который содержит ответ с этим изображением из JSR-133 Cookbook:

Reordering Rules Table

В соответствии с этим изображением преобразование компилятора из EDIT 3 является незаконным, поскольку оно переупорядочивает два монитора.

Кроме того, в этой таблице показано, какие ребра синхронизации - это какие-то "переупорядочивающие барьеры", для которых выполняются другие операции.

Благодарим за помощь:)