指令执行顺序
顺序执行
在早期处理器中,处理器执行指令的顺序就是按照我们编写汇编代码的顺序执行的。按序执行对于早期处理器而言是一种行之有效的方案,但随着对时间的要求,我们希望上述过程能够在最短的时间内执行完成,这就促使人们迫切希望找到一种优化指令执行过程的方案 。
乱序执行
随着处理器流水线技术和多核技术的发展,目前的高级处理器通过提高内部逻辑元件的利用率来提高运行速度,通常会采用乱序执行技术。打乱机器指令的顺序,就算指令位于后边,只要可以执行,就先执行,这就是乱序执行。 乱序执行的重要概念是实现了避免计算机在用于运算的对象不可获取时的大量等待。 在现代计算机中,处理器的运算速度大大超越了内存速度,所以在顺序执行处理器等待数据的过程中,乱序执行处理器能够执行大量的指令。
内存屏障
内存屏障是一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作。大多数现代计算机为了提高性能而采取乱序执行,这使得内存屏障成为必须。
作用
当基于共享可变状态的内存操作被重新排序时,程序可能行为不定。一个线程写入的数据可能被其他线程可见,原因是数据 写入的顺序不一致。适当的放置内存屏障通过强制处理器顺序执行待定的内存操作来避免这个问题。
内存屏障之前的所有写操作都要写入内存;内存屏障之后的读操作都可以获得同步屏障之前的写操作的结果。
分类
- 读屏障:在读指令之前插入读屏障,可以让高速缓存中的数据失效,重新从主内存加载数据;
- 写屏障:在写指令之后插入写屏障,能让写入缓存的最新数据写回到主内存;
性能
内存屏障阻碍了CPU采用优化技术来降低内存操作延迟,会造成一定的性能损失。
Java内存模型
volatile
Java内存模型中,当把变量声明为volatile类型后,会volatile变量在写操作之后会插入一个store屏障,在读操作之前会插入一个load屏障。因此不会将该变量上的操作与其他内存操作一起重排序,保证了volatile变量的可见性。
final
一个类的final字段会在初始化后插入一个store屏障,来确保final字段在构造函数初始化完成并可被使用时可见。