Может ли кто-то, кто понимает модель памяти Java лучше меня, подтверждаю мое понимание того, что следующий код правильно синхронизирован?
class Foo {
private final Bar bar;
Foo() {
this.bar = new Bar(this);
}
}
class Bar {
private final Foo foo;
Bar(Foo foo) {
this.foo = foo;
}
}
Я понимаю, что этот код правильный, но я не проработал весь процесс - перед математикой. Я нашел две неофициальные цитаты, которые предполагают, что это законно, хотя я немного опасаюсь полностью полагаться на них:
Модель использования конечных полей является простой: установите конечные поля для объекта в этом объектном конструкторе; и не пишите ссылку на объект, который строится в месте, где другой поток может видеть его до завершения конструктора объекта. Если это будет выполнено, тогда, когда объект будет замечен другим потоком, этот поток всегда будет видеть правильно построенную версию конечных полей этого объекта. Он также будет видеть версии любого объекта или массива, на которые ссылаются те последние поля, которые, по крайней мере, соответствуют последним, как конечные поля. [Спецификация языка Java®: Java SE 7 Edition, раздел 17.5]
Другая ссылка:
Что означает, что объект должен быть правильно сконструирован? Это просто означает, что никакая ссылка на объект, который строится, не может "убежать" во время строительства. (Примеры см. В разделе "Методы безопасного строительства" ). Другими словами, не размещайте ссылку на объект, который строится где угодно, где другой поток может его увидеть; не присваивайте его статическому полю, не регистрируйте его как слушателя с любым другим объектом и так далее. Эти задачи должны выполняться после завершения конструктора, а не в конструкторе. [JSR 133 (модель памяти Java) Часто задаваемые вопросы: "Как работают последние поля в рамках нового JMM?"