Files
Hui-s-notebook/锁优化.md
2023-09-10 10:50:53 +08:00

77 lines
3.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
### 自旋锁与自适应自旋
让线程等待一点时间,不放弃处理器执行时间,
让线程执行一个忙循环,
锁被占用的时间段,
可以避免线程切换的开销,但是要占用处理器时间
自适应的自旋:
自旋的时间不再固定,
而是由前一次在同一个锁上的自旋时间及锁的持有者的状态来确定
### 锁消除
即时编译器运行时,对检测到不可能存在共享数据竞争的锁进行消除,
主要判定依据来源于逃逸分析的数据支持
### 锁粗化
如果有一系列的连续操作都对同一个对象反复加锁和解锁,
甚至加锁操作是出现在循环体之中的,
虚拟机探测到有这样一串零碎的操作都对同一个对象加锁,
会把加锁同步的范围扩展(粗化)到整个操作序列的外部
### 轻量级锁
"轻量级"是相对于操作系统互斥量来实现的传统锁而言的
HotSpot虚拟机头部分为两部分
第一部分用于存储对象自身的运行时数据,
如哈希码、
GC分代年龄等
这部分在对应位数虚拟机中占用32或64各比特
称为"Mark World"
另一部分用于存储指向方法区对象类型数据的指针,
如果是数组对象,
还会有一个额外的部分存储数据长度
虚拟机在栈帧中建立一个名锁记录的空间,
用于存储锁对象目前的Mark World的拷贝
通过CAS修改将对象的Mark World更新为指向Lock Record的指针
这个动作成功了,就代表该线程拥有了这个对象的锁,
并且更新对象锁标志位为"00",表示该对象处于轻量级锁定
如果这个更新操作失败了,意味着至少存在一条线程与当前线程竞争,
虚拟机先检查对象的Mark World是否指向当前线程栈帧
如果是,说明当前线程已获得该对象的锁,
直接进入同步块执行,
否则该对象已被其他线程抢占。
如果过出现两条以上线程争用同一个锁,
轻量级锁不再有效,膨胀为重量级锁,锁标志状态变为"10"
Mark World中存储指向重量级锁的指针后面等待的线程进入阻塞状态
解锁操作同样通过CAS进行
如果对象的Mark World仍然指向线程的锁记录
用CAS操作把对象当前的Mark World和线程中复制的Displaced Mark World替换回来
如果能够成功替换,整个同步操作顺利完成,
替换失败,有其他线程尝试过获取该锁,
就要在释放锁的同时,唤醒被挂起的线程
### 偏向锁
目的是消除数据在无竞争的情况下的同步原语,进一步提高程序运行性能,
偏向锁在无竞争的情况下把整个同步都消除了CAS都不做了
锁对象第一次被对象获取时,
虚拟机把对象头中的标志位置设为"01",把偏向模式设置为"1"
表示进入偏向模式,
同时用CAS操作把获取到这个锁的线程ID记录在对象的Mark World中
CAS成功持有偏向锁的线程每次进入这个锁相关同步块时
虚拟机不进行任何同步操作。
一旦有另一个线程去尝试获取这个锁的状态,偏向模式马上宣告结束,
后续同步操作按照轻量级锁进行
当一个对象计算过一致性哈希码后,就应该一直保持不变
,就无法进入偏向锁了,
一个对象处于偏向锁状态收到计算一致性hash的需求后
偏向状态会立即撤销,锁膨胀为重量级锁