Будет ли JVM обновлять значение поля для всех потоков с использованием Happens-Before без прямого присвоения значения полю?

Я уже знаю, что если я пишу в энергонезависимое поле из другого потока, он, вероятно, сможет его кэшировать, поэтому все остальные потоки не увидят фактического значения. Но если я вызову, например, start() для объекта потока ПОСЛЕ присвоения значения в файл, JVM обновит это значение для всех других потоков. Но обновит ли JVM значение этого поля, если я выполню то же действие, но присвою значение полю не напрямую, например: object.field = 100, а с вызовом метода object.setFiled(100).

public class Main {
int value;

public static void main(String[] args) {
    Main main = new Main();
    main.value = 100;
    new Thread(() -> System.out.println(main.getValue())).start();
    

В этом случае значение поля будет одинаковым для всех остальных потоков.

}

public int getValue() {
    return value;
}
}

public class Main {
private int value;

public static void main(String[] args) {
    Main main = new Main();
    main.setValue(100);
    new Thread(() -> System.out.println(main.getValue())).start();

Но будет ли результат таким же в этом случае?

}

public int getValue() {
    return value;
}

public void setValue(int value) {
    this.value = value;
}
}

person zexed640    schedule 20.12.2020    source источник
comment
Существует фундаментальное заблуждение, показанное во фразе будет обновлять это значение для всех других потоков. Это не то, что происходит. Гарантии предоставляются только для потока, запущенного вызовом start(), в отношении записей, сделанных потоком, вызвавшим start(), до вызова. Никакой другой гарантии на любую другую резьбу не делается.   -  person Holger    schedule 20.12.2020


Ответы (1)


Механизм того, как что-то обновляется в потоке, будь то прямой доступ к полю или через сеттеры, в данном случае не имеет значения. В JLS 17.4.5 указано, что вызов start() в потоке происходит до любых действий в запущенном потоке. И внутри одного потока. Если x и y являются действиями одного и того же потока, и x предшествует y в программном порядке, то [x происходит раньше y]. В этом случае установщик метода или назначение поля, которые делают значение видимым для исходного потока, также делают это значение видимым для вновь запущенного потока. Грубо говоря, все, что было видно потоку, вызывающему start() во время вызова start(), будет таким же образом видимым для нового потока, если просматриваемый объект не мутирует и попытки просмотра состояния не мутируют. вещи (например, LinkedHashMap#get with accessOrder=true).

person John H    schedule 20.12.2020