Java 如果线程B希望看到线程A所做的更改,那么最后一次更改是否只能是一个可变变量,而不是全部?

Java 如果线程B希望看到线程A所做的更改,那么最后一次更改是否只能是一个可变变量,而不是全部?,java,multithreading,volatile,java-memory-model,memory-visibility,Java,Multithreading,Volatile,Java Memory Model,Memory Visibility,我已经看过了,它说明了如何: 在新的内存模型下,当线程A写入易失性 变量V,线程B从V读取 在编写V时A是可见的,现在保证是可见的 B可见 因此,举一个例子: public class Main { static int value = -1; static volatile boolean read; public static void main(String[] args) { Thread a = new Thread(() -> {

我已经看过了,它说明了如何:

在新的内存模型下,当线程A写入易失性 变量V,线程B从V读取 在编写V时A是可见的,现在保证是可见的 B可见

因此,举一个例子:

public class Main {
    static int value = -1;
    static volatile boolean read;

    public static void main(String[] args) {
        Thread a = new Thread(() -> {
            value = 1;
            read = true;
        });

        Thread b = new Thread(() -> {
            while (!read);

            System.out.println("Value: " + value);
        });

        a.start();
        b.start();
    }
}
尽管
(仅
读取
)无波动性,线程b是否仍能看到对
(从-1到1)的更改


如果是这样的话,考虑到为了让另一个线程可见而执行的一系列更改,除了最后一个变量是易失性的之外,更改任何变量是否有任何目的?

是的,对
值的更改保证对线程b可见

JLS表示:

  • 对易失性变量v的写入(§8.3.1.4)与任何线程对v的所有后续读取同步(其中“后续”是根据同步顺序定义的)
JLS表示:

两个动作可以由“发生在之前”关系排序。如果一个动作发生在另一个动作之前,那么第一个动作对第二个动作可见并在第二个动作之前排序

如果我们有两个动作x和y,我们写hb(x,y)来表示x发生在y之前

  • 如果x和y是同一线程的动作,并且x在程序顺序中位于y之前,那么hb(x,y)

  • 从一个对象的构造函数的结尾到该对象的终结器(§12.6)的开始,有一个before边

  • 如果动作x与后续动作y同步,那么我们还有hb(x,y)

  • 如果hb(x,y)和hb(y,z),那么hb(x,z)

项目符号1表示
value=1
发生在
read=true
之前 项目符号3表示
read=true
发生在
之前!阅读

子弹1说,
!read
发生在值:“+Value
之前

项目符号4表示
value=1
发生在
值之前:“+value

好的,记住这些规则,你能不能也讨论一下第二个问题(关于使用使变量上次不改变的变量)?@Theenjadev您想让我们推测一下,在某些情况下,是否需要使它们中的一个以上
不稳定
这里已经有了一个答案:如果最后一个更改的线程始终是另一个线程读取的第一个线程,那么就没有必要使其他线程不稳定。如果你不能做出保证,答案是:视情况而定!