首页
Web开发
Windows程序
编程语言
数据库
移动开发
系统相关
微信
其他好文
会员
首页
>
其他好文
> 详细
JVM锁优化
时间:
2018-09-09 20:06:32
阅读:
131
评论:
0
收藏:
0
[点我收藏+]
标签:
状态
use
高性能
code
结构
大小
图片
位置
遇到
1.锁优化
挂起线程和恢复线程的开销较大,对于锁定状态时间较短的情况下,挂起线程并不值得。
自旋锁与它的自适应自旋
遇到锁不会挂起,而是忙循环(自旋)一会儿,避免了一次线程切换的开销,但是仍在占用CPU时间。
1.6默认开启,默认自旋10次。
1.6还引入了自适应自旋锁,他可以根据上一次在同一个锁上的自旋时间调整自旋次数。
自旋失败则进入正常的挂起线程。
锁消除
JIT即时编译器在运行时如果发现某块代码上有同步,但是检测到该共享区域不可能存在竞争,就会进行锁消除。
如对某个局部变量操作时加了锁,但是局部变量不可能逃逸出方法,所以2个线程不可能对同一个局部变量存在竞争。此时就会消除锁。
JIT编译说明这段代码是热点代码,消除锁之后对性能提高有所帮助。
锁粗化
对一个对象反复的加锁解锁。如StringBuff的append()方法,编译器会优化到最外面一个锁。
轻量级锁
jvm实现无竞争情况下使用CAS操作消除同步使用的互斥量。
轻量级锁为什么可以提高性能就是因为 “绝大多数部分的锁在整个同步周期内都是不存在竞争的”,这是一个经验数据,如果不存在竞争使用CAS操作就可以避免使用同步互斥量的开销。
偏向锁
轻量级锁是无竞争情况下使用CAS操作取消使用同步互斥量,而偏向锁是无竞争情况下取消整个同步,连CAS都不用做。
偏向锁会偏向第一个获得他的线程,如果该锁没有被其他线程获取,那么持有偏向锁的线程就不会进行同步。
2.对象头
我们所说的某个对象的锁其实就是该对象的对象头中的几个标志位,该标志位改变为某个值说明该对象的锁被线程拿走了,释放锁后标志位恢复。
对象头分为2部分,第一部分存储对象自身运行时数据,第二部分存储类型指针。
自身运行时数据(Mark Word):如哈希码、GC分代年龄、锁转态标志、线程持有的锁,偏向线程ID、偏向时间戳。Mark Word是非固定的数据结构,以便存储更多信息,根据对象状态不同各个信息所占位数会变化,但总体肯定是8字节倍数。32位机下Mark Word占32bit,64位机下占64bit。
类型指针:指向元数据(Class类数据)的指针
如果对象是数组那么对象头还有一块用于记录数组长度的区域,因为普通Java对象通过元数据可以确定大小,而数组的元数据无法确定数组大小。
2.1 Mark Word 的不同状态下存储不同内容。
状态
标志位
存储内容
未锁定
01
对象哈希码。对象分代年龄
轻量级锁定
00
指向锁记录的指针
膨胀(重量级锁定)
10
指向重量级锁的指针
GC标记
11
空,不需要记录信息
可偏向
01
偏向线程ID、偏向时间戳、对象分代年龄
2.2 不同状态下不同信息所占的位数和位置
3.轻量级锁的实现和加锁过程。
程序并不是一遇到同步代码块立刻就拿到对象的重量级锁。
加锁
代码进入同步块时如果锁对象的标志位时01那么虚拟机会在当前线程的栈帧中建立一个 锁记录 空间 Lock Record,用来存储锁对象目前的Mark Word 的拷贝。
然后执行CAS 操作 ,它会比较锁对象的Mark Word 与拷贝是否相等。如果相等执行3,如果不等执行5
如果相等将锁对象的Mark Word 中的存储内容替换为 指向栈帧中拷贝的指针,此时这个线程就获得了该对象的锁,并且对象的锁标志位改为00。
此时栈帧中的Mark Word 存储的内容是(对象的hashCode,分代年龄,偏向锁位)而锁对象Mark Word 存储的内容是(指向栈中锁记录的指针),而且前者锁标志位01,后者锁标志位00.
如果不相等首先检查锁对象Mark Word内容是否指向当前线程,如果指向执行6,如果没有指向执行7
如果指向说明当前线程已经拿到了锁,则可以进入同步代码块执行,比如同步方法中调用同步方法,并且使用的同一个锁对象。
如果没有指向当前线程说明锁已经被别的线程拿到了,此时锁标志位改为10,锁对象Mark Word内容换为指向互斥量(重量级锁synchronized)的指针,然后执行8
注意此时线程发现拿不到锁也不会立刻被挂起,它会加入自旋,如果自旋一定次数失败就会进入阻塞状态。
解锁
首先查看锁对象的Mark Word内容是否指向栈,如果是那么就交换两者,同步代码执行完成。
如果没有,说明有别的线程来拿过锁,所以要解除互斥量同时唤醒被挂起的线程。
synchronized是不公平的不会按先后挂起顺序唤醒。
4.偏向锁
-XX:+UseBiasedLocking 启用偏向锁,1.6默认
锁对象第一次被线程获得,会把标志位设为01,此时线程ID还是空,对象还未锁定
通过一次CAS操作会把获取到这个锁对象的线程ID存入锁对象的Mark Word。此时对象已被锁定。
之后持有偏向锁的线程进入同步代码就不需要任何同步操作了。
如果另一个线程来获取锁,那么偏向模式就结束,分别如图按2种不同情况作出不同反应。
JVM锁优化
标签:
状态
use
高性能
code
结构
大小
图片
位置
遇到
原文地址:https://www.cnblogs.com/mibloom/p/9613598.html
踩
(
0
)
赞
(
0
)
举报
评论
一句话评论(
0
)
登录后才能评论!
分享档案
更多>
2021年07月29日 (22)
2021年07月28日 (40)
2021年07月27日 (32)
2021年07月26日 (79)
2021年07月23日 (29)
2021年07月22日 (30)
2021年07月21日 (42)
2021年07月20日 (16)
2021年07月19日 (90)
2021年07月16日 (35)
周排行
更多
分布式事务
2021-07-29
OpenStack云平台命令行登录账户
2021-07-29
getLastRowNum()与getLastCellNum()/getPhysicalNumberOfRows()与getPhysicalNumberOfCells()
2021-07-29
【K8s概念】CSI 卷克隆
2021-07-29
vue3.0使用ant-design-vue进行按需加载原来这么简单
2021-07-29
stack栈
2021-07-29
抽奖动画 - 大转盘抽奖
2021-07-29
PPT写作技巧
2021-07-29
003-核心技术-IO模型-NIO-基于NIO群聊示例
2021-07-29
Bootstrap组件2
2021-07-29
友情链接
兰亭集智
国之画
百度统计
站长统计
阿里云
chrome插件
新版天听网
关于我们
-
联系我们
-
留言反馈
© 2014
mamicode.com
版权所有 联系我们:gaon5@hotmail.com
迷上了代码!