Да, этот код является «правильным» в его нынешнем виде, начиная с Java 1.5.
Атомность не является проблемой, с или без энергозависимой (записи на ссылки на объекты являются атомарными), поэтому вы можете пересечь это из списка проблем в любом случае - единственный открытый вопрос - видимость изменений и «правильность», заказа.
Любая запись в изменчивую переменную устанавливает связь «произошла до» (ключевая концепция новой модели памяти Java, как указано в JSR-133) с любыми последующими чтениями одной и той же переменной. Это означает, что поток чтения должен иметь видимость во всем видимом для записывающего потока: то есть он должен видеть все переменные с не менее их «текущими» значениями во время записи.
Мы можем объяснить это в деталях, глядя на section 17.4.5 of the Java Language Specification, в частности, следующие ключевые моменты:
- «Если х и у являются действия одного и того же нити и х предшествует у в программном порядке, то ро (x, y) "(т. е. действия одного и того же потока не могут быть переупорядочены таким образом, чтобы они не соответствовали порядку программирования)
- « Запись в изменчивое поле (§8.3.1.4) происходит до каждого последующего чтения это поле ". (это поясняющий текст, объясняющий, что чтение-считывание летучего поля является точкой синхронизации)
- «Если hb (x, y) и hb (y, z), то hb (x, z)» (транзитивность происходит, перед тем)
Таким образом, в вашем примере:
- записываемый в «сервис» (а) происходит, перед записью в «serviceReady» (б), в связи с правилом 1
- запись в сервисный режим (b) происходит до того, как она считывается с тем же (c), из-за правила 2
- поэтому, (a) происходит-до (c) (3-е правило)
означает, что вам гарантировано, что «сервис» установлен правильно, в этом случае, как только serviceReady является истинным.
Вы можете увидеть некоторые хорошие записи окна используя почти точно тот же самый пример, один на IBM DeveloperWorks - см «Новые гарантии для Летучего»:
значения
, которые были видны А в то время, V была написана гарантированно теперь будет видна B.
и один в the JSR-133 FAQ, написанной авторами этой JSR:
Таким образом, если читатель видит значение true для v, также гарантировано, что запись будет записана до 42. Это не было бы правдой при старой модели памяти. Если v не были волатильными, то компилятор мог изменить порядок записи в записи, а чтение читателем x могло бы увидеть 0.
Вот почему мои глаза всегда пересекаются с JLS: мне показалось, что отношения «никогда раньше» не гарантируются нитями для нестабильной жизни. Спасибо за ссылку JSR-133, и мой ответ ушел. – kdgregory
Если serviceReady не является изменчивым, кажется, что завершение «записи в службу» (a) происходит до того, как вы напишите в «serviceReady» (b) «из-за правила 1. Но на самом деле это не так. Поэтому я чувствую, что в трех правилах есть что-то, чего не хватает. Как вы думаете? – zwy