多线程并发下的指令重排问题

在多线程并发情况下,指令重排会出现问题,先看下面一个例子:

public class DemoCount {

    public static int r1, r2, x, y;

    public static void main(String[] args) throws InterruptedException {
        boolean f1, f2, f3, f4;
        f1 = f2 = f3 = f4 = false;
        int count = 0;
        while (true) {
            r1 = r2 = x = y = 0;
            Thread t1 = new Thread(() -> {
                x = 1;
                r1 = y;
            });

            Thread t2 = new Thread(() -> {
                y = 1;
                r2 = x;
            });

            t1.start();
            t2.start();
            t1.join();// 确保线程0、1能够执行完main线程打印后面的输出结果
            t2.join();// 确保线程0、1能够执行完main线程打印后面的输出结果

            ++count;

            if (r1 == 0 & r2 == 1 & !f1) {
                System.out.println("第" + count + "次出现结果: r1=" + r1 + ":r2=" + r2);
                f1 = true;
            }
            if (r1 == 1 & r2 == 0 & !f2) {
                System.out.println("第" + count + "次出现结果: r1=" + r1 + ":r2=" + r2);
                f2 = true;
            }
            if (r1 == 0 & r2 == 0 & !f3) {
                System.out.println("第" + count + "次出现结果: r1=" + r1 + ":r2=" + r2);
                f3 = true;
            }
            if (r1 == 1 & r2 == 1 & !f4) {
                System.out.println("第" + count + "次出现结果: r1=" + r1 + ":r2=" + r2);
                f4 = true;
            }
        }
    }
}

运行会产生四种结果:

1次出现结果: r1=0:r2=159次出现结果: r1=1:r2=0359000次出现结果: r1=1:r2=147518222次出现结果: r1=0:r2=0

这里说明下,出现 r1=0r2=0 的情况表示出现了指令重排序,我们可以查看代码,两条代码交换位置其实是不影响结果,所以可以发生重排序,针对单线程来看,这种重排序是没有问题,但是多线程并发情况下就会出现问题,所以r1=r2=0 就是因为多线程情况下发生了指令重排序。

从上面这个例子我们可以通俗易懂的理解什么叫做指令重排。解决这个问题就可以使用原语 volatile 禁止指令重排序,底层通过四条内存屏障指令实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔道不误砍柴功

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值