У меня есть теоретический вопрос о модели памяти Java. Предположим, у меня есть сервер с этими двумя обработчиками запросов в следующем классе:
class MyHandlers {
volatile int someFlag = 0;
String handleFirstRequest() {
someFlag = 1;
return "Hello!";
}
String handleSecondRequest() {
return "value of someFlag: " + someFlag;
}
}
У меня также есть клиент. Мой клиент отправляет сетевой запрос, который запускает выполнение handleFirstRequest. Клиент ждет, пока запрос не завершится. Как только первый запрос завершается, клиент отправляет второй запрос, который вызывает handleSecondRequest.
Вопрос: Как модель памяти Java предотвращает ответ "value of someFlag: 0"
на второй запрос ?
Примечания: я понимаю, что на практике поток, обрабатывающий второй ответ, всегда будет видеть someFlag
как 1.
Если я правильно прочитал JMM, существует порядок синхронизации, который это общий порядок, который в моем примере упорядочил бы энергозависимое чтение и энергозависимую запись (someFlag = 1
). Если чтение следует за записью, тогда чтение увидит запись. Возможно ли иметь случай, когда запись следует за чтением? В этом случае запись не синхронизируется с чтением, и между записью и чтением не было бы никакой связи. Это приведет к тому, что поток, обрабатывающий второй запрос, увидит someFlag
как 0. Где мое понимание go неверно?
Дополнительные мысли (2020 Mar 2): JMM не обратитесь к понятию времени. Действия синхронизации упорядочены в соответствии с порядком синхронизации, но в JMM ничего не говорит о том, что порядок синхронизации такой же, как порядок действий, отсортированный по времени. Это предполагает, что реализация Java может упорядочить чтение someFlag
до записи, даже если чтение произошло после записи в соответствии с часами. Похоже, что JMM гарантирует, что , если упорядоченное чтение упорядочено после энергозависимой записи, затем записи до того, как энергозависимая запись станет видимой для чтения после энергозависимого чтения.