JVM 是否会使用 Happens-Before 更新所有线程的字段值,而不直接为字段赋值?
Will JVM update value of field for all threads with usage of Happens-Before, without assignment value to field directly?
我已经知道,如果我从另一个线程写入非易失性字段,他可能会缓存它,这样所有其他线程都看不到实际值。但是如果我在线程对象上调用 start()
AFTER assignment value to filed,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();
In this case value of field will be same for all other threads for sure
}
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();
But will be result same in this case?
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
在线程中如何更新某些内容的机制,无论是直接字段访问还是通过 setters 在这种情况下都无关紧要。 JLS 17.4.5 声明“线程上对 start() 的调用发生在启动线程中的任何操作之前。”在单个线程中“如果 x 和 y 是同一线程的操作,并且 x 在程序顺序中出现在 y 之前,那么 [x 发生在 y 之前]”。在这种情况下,使值对原始线程可见的方法 setter 或字段赋值也会使该值对新启动的线程可见。粗略地说,在调用 start() 时对调用 start() 的线程可见的任何内容都将对新线程同样可见,只要正在查看的对象没有发生变化并且查看状态的尝试没有发生变化东西(例如 LinkedHashMap#get with accessOrder=true)。
我已经知道,如果我从另一个线程写入非易失性字段,他可能会缓存它,这样所有其他线程都看不到实际值。但是如果我在线程对象上调用 start()
AFTER assignment value to filed,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();
In this case value of field will be same for all other threads for sure
}
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();
But will be result same in this case?
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
在线程中如何更新某些内容的机制,无论是直接字段访问还是通过 setters 在这种情况下都无关紧要。 JLS 17.4.5 声明“线程上对 start() 的调用发生在启动线程中的任何操作之前。”在单个线程中“如果 x 和 y 是同一线程的操作,并且 x 在程序顺序中出现在 y 之前,那么 [x 发生在 y 之前]”。在这种情况下,使值对原始线程可见的方法 setter 或字段赋值也会使该值对新启动的线程可见。粗略地说,在调用 start() 时对调用 start() 的线程可见的任何内容都将对新线程同样可见,只要正在查看的对象没有发生变化并且查看状态的尝试没有发生变化东西(例如 LinkedHashMap#get with accessOrder=true)。