一、JMM(Java线程内存模型)
1、JMM原子操作:read(读取):从主内存读取数据
load(载入):将主内存读取到的数据写入工作内存中。
use(使用):从工作内存读取数据来计算
assign(赋值):将计算好的值重新赋值到工作内存中
store(存储):将工作内存数据写入主内存
write(写入):将store过去的变量赋值给主内存中变量
lock(锁定):将主内存变量枷锁,标识为线程独占状态
unlock(解锁):将主内存变量解锁,解锁后其他线程可以锁定该变量
2、缓存一致性协议(MESI)
马上同步回主内存,其他cpu通过总线嗅探机制可以感知到数据的变化从而将自己缓存里的数据失效。
3、缓存加锁
缓存锁的核心机制是基于缓存一致性协议来实现的,一个处理器的缓存回写到内存会导致其他处理器的缓存无效。
4、 Volatile缓存可见性实现原理
底层实现主要通过汇编lock前缀指令,它会锁定这块内存区域的缓存(缓存行锁定)并回写到主内存。
lock指令解释:
会将当前处理器缓存行数据立即写回到系统内存。
写回内存的操作会引起在其他CPU里缓存了该内存地址的数据无效(MESI协议)
提供内存屏蔽功能,使lock前后指令不能重排序。
使用volatile修饰后再汇编语言中图解:
解释:内存屏障:在JDK中使用C++语言编写代码中会使用下列指令。
5、并发编程三大特性:可见性、有序性、原子性。
volatile保证可见性、有序性;synchronized保证原子性
指令重排序:再不影响单线程程序执行结果的前提下,计算机为了最大限度发挥机器性能,
会对机器指令重排序优化。
重排序会遵循as-if-serial与happens-before原则
解释:as-if-serial语义:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程
序的执行结果不能被改变。
二、锁
1、案例
测试代码:
版本一:运行结果1000ms
版本二:运行结果400ms,AtomicInteger。
2、AtomicInteger,CAS(轻量级锁、自旋锁)
上述incrementAndGet()方法:
解释:compareAndSet:此方法在程序底层(JDK)使用了lock锁(硬件级别的锁)。
3、ABA问题
问题:线程1准备修改A到B,此时线程2抢到执行权在线程1前执行,线程2把A改到C在改到A。此时线程1认为值A没有变,但是线程2还是做了操作。
解决:加一个Version,设置版本号。就不会对比值,对比版本号。
AtomicInteger没有,AtomicStampedReference有。
4、synchronized锁优化
synchronized在JDK1.6后做了升级
5、对象组成
对象在运行中的存储结构
解释:OFFSET:
0、4:一共8字节64位,对应对象头中markword中的前两个,同时对应第二张图
8:对应对象头中markword中的Metedata原数据指针。
12、16:实例数据,
20:对齐填充,对象需要被8个字节整除,如果不够这里做补充。作用寻址更快。