Это из JLS 17.5:
Модель использования для конечных полей проста. Установите последние поля для
объект в конструкторе этого объекта. Не пишите ссылку на объект, являющийся
построен в месте, где другой поток может увидеть его перед конструктором объекта
закончен. Если это следует, то когда объект виден другим потоком,
этот поток всегда будет видеть правильно построенную версию финального объекта
поля. Он также увидит версии любого объекта или массива, на которые ссылаются эти последние
поля, которые по крайней мере так же актуальны, как и последние поля.
Обсуждение в JLS 17.5 включает в себя этот пример кода:
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
Я попытался использовать этот код, чтобы повторить ситуацию, описанную выше, и вот что у меня есть:
public class FinalFieldThread extends Thread {
public static void main(String[] args) {
ThreadA threadA = new ThreadA();
ThreadB threadB = new ThreadB();
threadB.start();
threadA.start();
//threadB.start();
}
}
class ThreadA extends Thread {
@Override
public void run() {
System.out.println("ThreadA");
FinalFieldExample.writer();
}
}
class ThreadB extends Thread {
@Override
public void run() {
System.out.println("ThreadB");
FinalFieldExample.reader();
}
}
Я могу проверить, правильно ли читается final, но как я могу выполнить репликацию, когда он не читается правильно (т. Е. Когда есть ссылка на протектор до завершения работы конструктора?)