java - 如果线程B希望看到线程A所做的更改,那么最后更改只能是volatile变量而不是全部变量吗?

标签 java multithreading volatile java-memory-model memory-visibility

我看过this answer,它说明了如何:

Under the new memory model, when thread A writes to a volatile variable V, and thread B reads from V, any variable values that were visible to A at the time that V was written are guaranteed now to be visible to 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();
    }
}

尽管value不可变(仅value),但是否仍对线程b看到read的更改(从-1到1)?

如果是这样的话,给定一系列更改是为了使另一个线程可见,那么除了最后一个可变变量之外,是否要对其他任何变量进行更改,是否有任何目的?

最佳答案

是的,保证对value的更改对于线程b是可见的。
JLS 17.4.4. Synchronization Order说:

  • A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order).

JLS 17.4.5. Happens-before Order说:

Two actions can be ordered by a happens-before relationship. If one action happens-before another, then the first is visible to and ordered before the second.

If we have two actions x and y, we write hb(x, y) to indicate that x happens-before y.

  • If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).

  • There is a happens-before edge from the end of a constructor of an object to the start of a finalizer (§12.6) for that object.

  • If an action x synchronizes-with a following action y, then we also have hb(x, y).

  • If hb(x, y) and hb(y, z), then hb(x, z).


项目符号1表示value = 1read = true之前发生。
项目符号3说read = true!read之前发生。
项目符号1表示!read"Value: " + value之前发生。
项目符号4表示 value = 1"Value: " + value 之前发生。

关于java - 如果线程B希望看到线程A所做的更改,那么最后更改只能是volatile变量而不是全部变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52580872/

相关文章:

c++ - 对共享数据的线程安全访问 - 读/写实际上发生并且不会发生重新排序

java - 每天根据 log4j2 中的每小时在新目录中生成日志?

java - 如何使用 Spring Security 命名空间设置和配置 ProviderManager?

c++ - dup 竞赛后的 pwrite 安全吗?

objective-c - 如何使对象接收到的每条消息都是线程安全的?

java - 并行运行 junit 测试时的竞争条件

java.text.ParseException : Unparseable date: "06-DEC-11"

java - 未找到 GWT Java MySQL 选择查询列但在 phpMyAdmin 中正常

c++ - 为必须可平凡复制的 volatile 结构分配一个值

c# - volatile 应该与(非并发)集合一起使用吗?