@ Энди Тернер частично прав.
Добавление synchronized
к методу get()
влияет на требования к видимости памяти и приводит к тому, что компилятор (JIT) генерирует другой код.
Однако, строго говоря, должна быть , прежде чем связывает вызов set(...)
и вызов get()
. Это означает, что метод set
должен быть synchronized
, а также get
(если вы собираетесь сделать это таким образом!).
Короче говоря, версия вашего кода, на которой вы работали, НЕ гарантированно будет работать на всех платформах и при любых обстоятельствах. На самом деле вам повезло!
Читая между строк, кажется, что вы пытаетесь на экспериментальной основе выяснить, как работает модель памяти Java. Это не очень хорошая идея. Проблема в том, что вы пытаетесь реконструировать очень сложный черный ящик без достаточного количества «входных параметров» 1 , чтобы вы могли варьируются, чтобы охватить все потенциальные аспекты поведения черных ящиков.
В результате подход «обучение через эксперимент» может оставить вас с неполным или ошибочным пониманием.
Если вы хотите получить полное и точное понимание, вы должны начать , читая о модели памяти Java в хорошем учебнике ... или самом JLS. Во что бы то ни стало, используйте эксперименты, чтобы попытаться подтвердить свое понимание, но вы должны знать, что JMM определяет (гарантирует) только , что происходит, если вы поступаете правильно. Если вы поступите неправильно, ваш код может работать в любом случае ... в зависимости от всевозможных факторов. Следовательно, часто трудно получить экспериментальное подтверждение того, что определенный способ ведения дел является правильным или неправильным 2 .
1 - Некоторые параметры, которые вам понадобятся, на самом деле не существуют. Например, тот, который позволяет вам запускать Java N для N> 12, или тот, который позволяет вам работать на оборудовании, к которому у вас нет доступа ... или которого еще нет.
2 - Как показано на вашем примере. Вы получаете «правильный» ответ, даже если код неправильный.