Модель памяти Java: безопасно ли создавать циклический граф ссылок из полей конечных экземпляров, все они назначены в одном потоке?

Может ли кто-нибудь, кто лучше меня понимает модель памяти 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?"]

Ответы на вопрос(2)

Ваш ответ на вопрос