指令重排序举的例子的疑问

来源:12-4 相关概念

扶摇羊角

2021-02-17

public class OutOfOrderExecution {
    private static int x = 0, y = 0;
    private static int a = 0, b = 0;
    private static CountDownLatch countDownLatch = new CountDownLatch(1);

    public static void main(String[] args) throws InterruptedException {
        int i = 0;
        for (; ; ) {
            i++;
            x = 0;
            y = 0;
            a = 0;
            b = 0;

            Thread one = new Thread(() -> {
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                a = 1;
                x = b;
            });

            Thread two = new Thread(() -> {
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                b = 1;
                y = a;
            });

            two.start();
            one.start();
            countDownLatch.countDown();
            one.join();
            two.join();
            System.out.println("第" + i + "次 x = " + x + ", y = " + y);
            if (x == 0 && y == 0) {
                break;
            }
        }
    }
}

对于课程中关于重排序举的这个例子,由于是在两个线程中对于共享变量的操作,这种操作是线程不安全的,即使当两个线程运行完成,x = 1,y = 1,那么这时主存中的x和y还未得到更新,则会出现x = 0,y = 0的情况,我的理解是这种并非发生了指令重排序。

麻烦解答一下?

写回答

1回答

悟空

2021-02-17

从现象上看,无法判断是未更新还是发生了重排序,因为现象都是一样的。

但是happens-before的规则之一:join()规则:如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。

所以主内存一定能看到子线程执行的结果。

0
0

线程八大核心+Java并发原理及企业级并发解决方案

完整的并发知识网络+丰富的工作内容分享+50余道并发高频面试题

2512 学习 · 939 问题

查看课程