在Java中发生的事先机制

时间:2014-08-02 19:19:02

标签: java multithreading volatile java-memory-model

我在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);
        }


    }

这是发生在之前的明显例子,这是足够安全的,据我所知。 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);


    }
}

1 个答案:

答案 0 :(得分:4)

b volatile设置为write并将值设置为b后,a保证:

  1. 如果在b之前阅读a,则
  2. a的值不会超过之前写入b时的值。
  3. 即,b的写入和b的读取充当同步点或栅栏,这意味着在写入{{1}之前写入a的任何内容从b读取后将可读取(如果b被写入多次,则以下写入可能会或可能不会显示)。

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

    read

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

    至于a中的重新排序操作 - 这将明确消除a排序保证对write上的操作的影响,即使b首次读取a 1}}然后阅读read

    要想象事物,仅b ab

    当前代码不保证在 -

    上对操作进行排序
    volatile

    使用给定的读取重新排序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