Итоговые поля Vs. Летучий - PullRequest
0 голосов
/ 29 мая 2020

Из java документов окончательной field семантики:

Окончательное поле в JDK14

Они гарантируют, что поле final будет установлено в constructor, пожалуйста, найдите код ниже:

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
        } 
    } 
}

Теперь я не понимаю volatile vs final.

Насколько я понимаю, final fieldd используется make уверен, что вы не можете изменить переменную в приложении, и volatile гарантирует поддержание порядка и предотвращение того, что произойдет до отношений.

Итак, мой вопрос в том, почему они гарантируют видимость и упорядочение с использованием переменной final вместо volatile? Пожалуйста, помогите.

1 Ответ

1 голос
/ 29 мая 2020

Итак, мой вопрос в том, почему они гарантируют видимость и упорядочение с использованием конечной переменной

Потому что они определили это таким образом, и теперь задача виртуальной машины - придерживаться этого определения .

Конечно, следующий вопрос: почему они так определили это?

Это из-за странной «особенности» модели памяти Java. Рассмотрим этот пример.

class Foo {
    int x;
    volatile int y;
    Foo() {
        x = 3;
        y = 4;
    }

    static final Foo INSTANCE;
    static {
       INSTANCE= new Foo();
    }
}

Инициализатор stati c будет скомпилирован в этот (упрощенный псевдокод):

   Foo tmp = allocate(Foo.class)
   Foo.INSTANCE = tmp
   tmp.x = 3
   tmp.y = 4

Как видите, экземпляр сделан publi c перед выполнением конструктора volatile здесь ничего не меняет.

Такое поведение неожиданно для большинства разработчиков и может привести к очень сложным для отладки ошибкам. Таким образом, чтобы немного уменьшить масштабы этой проблемы, спецификация была скорректирована таким образом, чтобы требовать инициализации полей final перед публикацией экземпляра c.

Пример сверху, с объявлением x final.

   Foo tmp = allocate(Foo.class)
   tmp.x = 3
   Foo.INSTANCE = tmp
   tmp.y = 4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...