如果你不想平庸,就请勿停止前进的脚步。同样作为主流的开发语言,Java也没有停止前进,而是一直在优化进步。更多内容请搜索关注微信公众号:Different Java
摘要
- 为什么需要锁优化
- 锁的状态
- 偏向锁
- 轻量级锁
- 锁升级
- 锁消除
1. 为什么需要锁优化
synchronized Lock在JDK1.6之前效率低下,原因我们已经在悲观锁中讲述过了,因此为了提高锁的效率,JVM对其进行了优化。
2. 锁的状态
锁优化的过程也是锁状态变更的过程,锁的状态目前有以下几种:
- 无状态锁
- 偏向锁
- 轻量级锁
- 重量级锁
锁的状态是如何标记的,这就需要借助Java对象在内存中的存储格式。Java对象在虚拟机中大致分为三部分:
- 对象头
- 实例数据
- 对齐填充
对象头中存储对象自身运行时的数据(Mark Word)以及类型指针,而锁的状态则保存在Mark Word中。 由于锁状态的不同,Mark Word也会不相同。各种锁状态下的Mark Word(32位 JVM)如下:
3. 偏向锁
如果一个线程获得了锁,那么锁就进入偏向模式,此时对象的Mark Word也会进入偏向锁模式,当该线程再次请求锁无需执行获取锁操作,省去了大量获取锁的时间。对于竞争不激烈的场合偏向锁的提升效果还是很明显的,但是竞争激烈的场合建议关闭偏向锁,可以使用-XX:-UseBiasedLocking此参数关闭偏向锁。
偏向锁的锁定和撤销的简要步骤如下:
4. 轻量级锁
当偏向锁失败时,虚拟机不会立即挂起线程。它会将对象头部作为指针,指向持有锁的线程堆栈内部,来判断一个线程是否持有对象锁。如果成功,则可以进入临界区,失败以后会膨胀为重量级锁,但是膨胀后,虚拟机还会做最后一次努力优化,那就是自旋锁。
轻量级锁膨胀重量级锁的简要步骤如下:
5. 自旋锁
由于当前线程暂时无法获得锁,但何时获取也是未知的。有可能在几个CPU时钟周期后便可得到锁,此时虚拟机或进行一次赌注,会让当前线程做几个空循环,在经过若干次循环后如果可以得到锁便进入临界区,如果不能获得锁,则将线程真正从操作系统层面挂起。
6. 锁升级
锁只能升级不能降级,锁升级的详细步骤如下:
7. 锁消除
锁消除是JVM运行时通过JIT编译来发现不可能存在共享资源竞争的锁,然后将其消除(消除的关键是要借助逃逸分析),节省无意义的请求时间。
本期的Java锁优化就介绍到这,我是shysh95,我们下期再见!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。