Мой вопрос касается безопасных публикаций значений полей в Java (здесь здесь не указано Java multi-threading & Safe Publication).Безопасная публикация, когда значения считываются синхронными методами
Как я понимаю, поле можно безопасно прочитать (то есть доступ из нескольких потоков будет видеть правильное значение), если:
- чтения и записи синхронизированы на одном мониторе
- поле является окончательным
- поле является летучим
Если я правильно понимаю следующий класс должен не поточно-, так как начальное значение записывается без этих характеристик. Однако мне трудно поверить, что мне нужно сделать first
volatile
, хотя он доступен только из метода synchronized
.
public class Foo {
private boolean needsGreeting = true;
public synchronized void greet() {
if (needsGreeting) {
System.out.println("hello");
needsGreeting = false;
}
}
}
Я что-то не хватает? Правильно ли указан код и если да, то почему? Или необходимо в таких случаях сделать first
volatile
или использовать final AtomicBoolean
или что-то в этом роде дополнительно для доступа к нему из метода synchronized
.
(Просто чтобы прояснить, я знаю, что если начальное значение было написано в методе synchronized
было бы потокобезопасной даже без volatile
ключевого слова.)
«[...], из которого вытекает, что не происходит - до края от конца конструктора объекта до начала произвольного метода!». Эта «импликация» неверна. – Grodriguez
О, конечно, это не формальное значение. Однако тот факт, что они утверждают, что конец конструктора происходит до начала метода финализатора, будем говорить «намеки на», что это может быть неверно для произвольных методов. – aioobe
@aioobe no, это просто для таких случаев, как следующий код: 'new SomeObject()', т. Е. Вызывает конструктор, но не сохраняет ссылку. Затем объект может сразу же быть собрано в мусор, и финализатор может быть немедленно вызван. Предложение, о котором вы говорите, просто гарантирует, что конструктор все еще закончит работу до завершения финализатора. –