Семантика конечных полей в потоках

Это из JLS 17.5:

Модель использования полей final проста. Установите последние поля для объект в конструкторе этого объекта. Не писать ссылку на объект, построенный в месте, где другой поток может видеть его перед конструктором объекта закончен. Если это будет выполнено, то, когда объект увидит другой поток, этот поток всегда будет видеть правильно построенную версию окончательного поля. Он также увидит версии любого объекта или массива, на которые ссылаются последние поля, которые по крайней мере так же актуальны, как и последние поля.

Обсуждение в 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 читается правильно, но как я могу реплицировать, когда он не читается правильно (например, когда есть ссылка на протектор до того, как конструктор закончил?)

6
задан Isaac 29 February 2012 в 07:29
поделиться