compare and swap / compare and exchange
比较并交换
过程:
在内存里有一个数值,我们先读取这个数值,存起来,然后当我们需要改变内存值的时候,把提取出来的数值和内存里的值进行比较,如果相同就说明没人更改过数据,就可以直接写入内存。这里不需要锁,这个过程称为 无锁 或者 自旋锁
ABA问题:
就是本来这个内存里的数值为A,经过一次操作变成了B,然后又经过一个操作又变回了A,这就是ABA问题,怎么解决这个问题呢?
加一个版本号
CAS的底层实现:
lock cmpxchg 汇编指令(不是原子操作)
cmpxchg :compare and exchange , 这不是原子操作,所以在进行数据交换的过程中,被其他cpu的操作打断。
所以指令前面就加了一个 lock 指令,让其cpu操作打断不了交换过程。这个是针对多CPU
JOL = Java Object Layout 对象内存布局(工具)
markword 8个字节
class pointer
instance data
padding
markword:锁定某个对象,修改markword
markword记录了哪些信息: 锁信息,gc信息和 hashcode
锁升级初步
用户态与内核态
我们在进行一些比较危险的操作 ,比如说格式化银盘的时候,我们需要经过kernel内核态的允许。
jdk早期,synchronized叫做重量级锁, 因为申请锁资源必须通过kernel,系统调用,效率偏低
重量级锁:
就是指某些特殊操作需要经过内核态kernel的允许
锁升级/锁优化
就是指 让我们的某些操作不需要经过kernel内核的允许
markword 是一个 8 字节构成的,里面包含了 锁,GC, hashcode的信息
最后两位是锁标志位
00 : 表示 轻量级锁 / 自旋锁 / 无锁(CAS)
10 : 重量级锁
11: GC标记信息
001 : 无锁态
101 : 偏向锁
偏向锁
开启的 时候有延迟
把自己的id号 贴到了markword上,当前线程指针 javaThread*
为什么会有偏向锁?
多数synchronized方法,在很多情况下, 只有一个线程在运行
偏向锁如何变成 轻量级锁
轻度竞争------- 轻量级锁
不需要经过内核
为什么有自旋锁还需要重量级锁?
自旋锁是消耗资源的,如果锁的时间长,或者自旋 线程多,cpu会被大量消耗
重量级锁有等待队列,所有拿不到所得进入等待队列,不需要消耗cpu资源