【问题标题】:Happens-before mechanism in JavaJava中的Happens-before机制
【发布时间】:2014-08-02 19:19:02
【问题描述】:

我有一个关于 Java 中发生前发生机制的问题。示例如下:

public class MyThread extends Thread {

        int a = 0;
        volatile int b = 0;

        public void run() {


            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            read();
        }

        public void write(int a, int b) {
            this.a = a;  
            this.b = b;
        }

        public void read() {
            System.out.println(a + " " + b);
        }


    }

据我所知,这是happens-before 的明显示例,而且足够安全。 a 将正确获得新值,因为它位于 b 的初始化之前。但重新订购是否意味着安全得不到保障?我说的是这个:

public void write(int a, int b) {
    this.b = b;
    this.a = a;//might not work? isn't it?
}

UPD主线程:

public class Main {

    public static void main(String[] args) throws InterruptedException {

        MyThread t = new MyThread();
        t.start();
        t.write(1, 2);


    }
}

【问题讨论】:

  • 能否添加包含 start() 调用的代码?我无法准确理解你在这里问什么

标签: java multithreading volatile java-memory-model


【解决方案1】:

创建b volatile 并让write 在将值设置为b 之后将值设置为a 保证:

  1. 如果ba之前被读取,那么
  2. a 的值不会早于之前写入 b 时的值。

即,对b 的写入和对b 的读取充当同步点或栅栏,这意味着在写入b 之前写入a 的任何内容将在读取之后可读来自b(如果a 被多次写入,以下写入可能可见也可能不可见)。

但是,您的代码不像现在这样安全。在read 中,您有以下表达式:

a + " " + b

在 Java 中,expressions are evaluated left-to-right。这意味着,a 将在 b 之前进行评估。因此,完全有可能读取a 将看到旧值a,而读取b 将看到新值b。如果您在a 之前读取了b,那么b 的写入和读取之间的发生前关系将涵盖写入a 和读取a。现在,它没有。

至于write 中的重新排序操作——这将清楚地消除b 的排序保证对a 的过度操作的影响,即使read 首先读取b,然后读取a

为了形象化,只给bvolatile

当前代码不保证 a - 上的操作顺序

write a                         read a
write b --> happens before -->  read b

使用给定读取重新排序 write 也不会排序 a -

                                read a
write b --> happens before -->  read b
write a

即使给定的read 是固定的,a 也不会被b 排序-

write b --> happens before -->  read b
write a                         read a

唯一安全的做法是保留当前的write,并修复read -

write a
write b --> happens before -->  read b
                                read a

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-13
    • 2019-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多