【并发】JMM三大特性


JMM 是抽象的内存规范

对变量有改操作后,会把结果回写回来。
,先用assign 把执行引擎的数据同步到工作内存中,然后从工作内存store出来,再用write到主内存中。
必须把它的工作内存的数据同步到主内存中
在这里插入图片描述


八大

java并发的三大特性:

  • 可见性
  • 原子性
  • 有序性

可见性

每个线程只能看到自己的工作内存的更改, 加一个volatile可以及时的看到,但是不加volatile线程在一定的时间之后也会看到,只是看到的时机确定不了。
volatile是java并发轻量级的锁机制
线程B改了initFlag后就会主动通知线程A,让线程A去主内存再拿一次
在这里插入图片描述


加了volatile后字节码层面会给这个initFlag变量加一个ACC_VOLATILE标记
在这里插入图片描述

原子性

加了volatile也不能保证原子性,要用synchronized或者lock去保证原子性。

counter++ 相当于分了三步(读、自加、写回),这三步每一步是原子的,但是这三步加在一起不能保证原子性。因为如果执行了一步就被切到另一个线程后,另一个线程对counter修改后因为加了volatile会通知线程A 去主内存读新的,那之前执行的就会扔掉 就少加了一次。
在这里插入图片描述

有序性

指令重排

我们的java代码的顺序 不是CPU执行指令的顺序,他会进行指令重排比如a和b都依赖z变量 ,如果b指令是在很后面 就会被提前到和a指令一起加到缓存去
volatile可以解决指令重排

代码证明确实有指令重排的情况

  • 第一种:x=0,y=1
    在这里插入图片描述

  • 第二种:x=1,y=0

在这里插入图片描述

  • 第三种 x=1,y=1
    在这里插入图片描述
  • 指令重排则会出现 x=0,y=0
    在这里插入图片描述

指令重排的危害

内存屏障

volatile 中加了内存屏障

我们也可以自己手动加内存屏障,用Unsafe类的以下三个方法:
在这里插入图片描述
在这里插入图片描述


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章