volatile原理/指令重排

1、volatile关键字

volatile关键字有如下两个作用:
     保证被volatile修饰的变量对所有线程总数可见的。
     禁止指令重排序优化。

场景:一个线程写,一个线程读
    写一个volatile变量,会把它刷新到主内存中。
volatile如何禁止指令重排:
    内存屏障:CPU指令,插入内存屏障禁止在内存屏障前后的指令执行重排序优化。内存屏障的另外一个作用是强制刷出各种CPU的缓存数据。

2、指令重排(对单线程没有影响)

计算机在执行程序时,为了提高性能,编译器和处理器的常常会对指令做重排,一般分以下3种:
编译器优化的重排
指令并行的重排
内存系统的重排

2.1:编译器重排

线程 1             线程 2
1: x2 = a ;      3: x1 = b ;
2: b = 1;         4: a = 2 ;
******排序后******
线程 1              线程 2
2: b = 1;          4: a = 2 ; 
1:x2 = a ;        3: x1 = b ;

这种执行顺序下就有可能出现x1 = 1 和x2 = 2 的情况,这也就说明在多线程环境下,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性是无法确定的。

2.2:处理器指令重排

处理器指令重排是对CPU的性能优化,CPU在工作时,需要将上述指令分为多个步骤依次执行。为了提高硬件利用率,CPU指令是按流水线技术来执行的

       R1:IF ID EX MEM WB
       R2:    IF ID EX  MEM WB
ADD R1,R2:       IF ID   X  EX  MEM WB

X指令代表停顿,执行ADD指令时需要使用到前面指令的数据R1,R2,而此时R2的MEM操作没有完成,必须等到MEM操作完成后才能执行.
既然ADD指令需要等待,那我们就利用等待的时间做些别的事情.(指令重排)

3、JMM内存模型

JMM内存模型(线程--->工作空间(线程)--->内存)
多个线程访问时,会将内存中的数据复制一份到当前线程的工作空间去,待修改完成后在刷新到主内存中。

工作空间对应:cpu的寄存器--->cache(高速缓冲存储器)--->内存
//当CPU在CACHE中操作数据时(共享变量),数据在CACHE读到寄存器中,进行修改,并更新内存数据。

注:此文章是个人经过阅读书籍/网站等整理而成的。具体哪个网站记不清了,若有雷同,请留言我删除!

你可能感兴趣的:(volatile原理/指令重排)