0
点赞
收藏
分享

微信扫一扫

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


系列文章目录

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

文章目录

  • ​​系列文章目录​​
  • ​​前言​​
  • ​​一、什么是指令重排序​​
  • ​​1、示例1-1:​​
  • ​​二、为什么要做指令重排序​​
  • ​​三、重排序的原则​​
  • ​​总结​​

前言

其实一直想写一篇关于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怎么保证数据一致性(一)为什么要做指令重排序?_java


流程就是:把数据取出放到寄存器上->执行指令->把结果存下来

这里面有十几个流程,而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怎么保证数据一致性(一)为什么要做指令重排序?_java_02

上面的例子中,最大化地利用了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开发工具》​​,如果你感兴趣可以来看看


举报

相关推荐

0 条评论