多核cpu怎么保证数据一致性(一)为什么要做指令重排序?

系列文章目录

多核cpu怎么保证数据一致性(一)为什么要做指令重排序?
多核cpu怎么保证数据一致性(二)cpu为什么要用高速缓存?L1,L2,L3 cache
多核cpu怎么保证数据一致性(三)MESI缓存一致性协议
多核cpu怎么保证数据一致性(四)volatile关键字、happens-before原则、内存屏障


前言

其实一直想写一篇关于cpu的指令运算与java代码相结合的文章,今天,它来了,本文主要介绍java的指令怎么在最高的运用电脑cpu性能的情况下保证正确的执行,会涉及到指令重排序、happens-before、内存屏障等知识点,由于知识点较多,会分为几篇文章去讲


一、什么是指令重排序

1、示例1-1:

        int a = 1;
        int b = 2;
        a=a+1;
        b=b+1;

可能会被优化成如下顺序:

        int a = 1;
        a=a+1;
        int b = 2;
        b=b+1;

我们会发现指令的顺序变了,但是执行结果不会变。

二、为什么要做指令重排序

其实做指令重排序的目的,你肯定猜得到肯定是为提升性能么。
但是具体的原理是什么呢?
其实这跟cpu相关,在cpu中,处理一个指令,例如“b=a+1”,是包含一系列工序的,如下所示:
cpu流水线
流程就是:把数据取出放到寄存器上->执行指令->把结果存下来
这里面有十几个流程,而cpu呢,同一时间只能执行一个流程,无法并发执行,举例如下:

        a=a+1;
        b=b+1;

单个cpu在取a的值的时候,无法并行取b的值,在a的取指指令完成,执行下一步“执行”指令的时候,才能去取b的值,就是cpu同一时间只能执行一道工序,无法并发执行。
此时你可能想把“a=a+1”执行完了,再执行"b=b+1"不就行了么,如果这样的话,一个执行执行要花十几道工序,在执行其中一道工序的时候,其他工序都空着,是很浪费的,其实在a的取指指令执行完成,就可以执行b的取指指令了(注意:现在cpu一个取指都会分3-4道工序,其实取指的第一道工序执行完进入第二道工序,就可以执行下一条指令的第一道工序了,这里为了方便你的理解,所以做了简化说明,我认为理解到这个程度就够了,说明你已经理解了原理,在深入也没有必要)。

流水线

上面的例子中,最大化地利用了cpu,但是你看看下面这个问题,还能不能按照上面说的原理进行呢?

        a=a+1;
        x = a+2;
        b=b+1;

此时“x=a+2”,下条指令的参数用到了上条指令的结果,这时候就要等到第一条指令完全执行完才能执行第二条了吧。否则a=a+1的结果没出来啊。此时你发现"b=b+1",这第三条指令跟前面没有关系啊,那是不是可以先执行第三条呢,否则,cpu一直空着,这多么浪费资源啊。对,这样就产生了指令重排序。

三、重排序的原则

上面我们说了指令重排序,那么指令重排序一定要有一定的原则吧:
核心原则就是:不管怎么进行指令重排序,单线程内程序的执行结果不能被改变。
在java中还有一个happens-before原则,下一节,我们就聊聊happens-before原则和其实现原理

总结

我们在上文中,用代码示例展示了

  • 什么是重排序,
    就是把指令不按照代码看上去的顺序执行,但是对结果没有影响
  • 为什么要做指令重排序:为了提升cpu的性能和利用率
  • 重排序的基本原则:不管怎么进行指令重排序,单线程内程序的执行结果不能被改变。

其实我一直认为,工欲善其事,必先利其器,在工具的使用上,我准备了专栏《java开发工具》,如果你感兴趣可以来看看

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值