专业的JAVA编程教程与资源

网站首页 > java教程 正文

jvm synchronized锁、偏向锁、自旋锁略解

temp10 2025-06-23 21:45:47 java教程 2 ℃ 0 评论

java中任何对象都可以作为锁对象,对象包含markword、body、classword等。

对象头格式:

jvm synchronized锁、偏向锁、自旋锁略解


锁记录:加锁时线程栈帧中创建的一个对象,包含的字段有锁对象的引用(指针),锁对象的地址

每个锁对象可以关联一个jvm层次的Monitor对象,假设现在有两个线程分别为t0和t1。还是使用我们的synchronized关键字对临界区代码进行加锁。



假设目前t0加锁成功,并且t1没有与t0进行竞争,所以目前t0加上的锁是轻量级锁,将锁对象的markword字段与t0线程栈帧中锁记录地址CAS交换成功,锁对象的锁标志为轻量级锁。然后轻量级锁解锁时,再使用CAS交换t0线程栈帧中的锁对象的markword和和锁对象中的锁记录,交换成功则解锁。

上面解锁是在没有其他线程进行竞争情况下的流程,假如t1在t0上锁之后也请求该锁对象,也进行t1线程栈帧中锁记录地址CAS的交换,但是发现该锁对象的加锁状态为true,所以加锁失败,然后此锁对象的锁标志也升级为重量级锁,在t0解锁的时候发现锁已经升级为重量级锁,然后就将该锁对象的OWNER设置为空,唤醒entryList中受阻塞的线程。


自旋优化

重量级锁进行竞争时,会进行自旋优化以避免线程切换(切换为引起阻塞)。jdk1.7以后程序员无法控制是否开启自旋锁


偏向锁

只有第一次使用CAS将线程id替换到对象markword中,之后该线程再次获取锁的时候发现是自己的线程id,就不需要进行cas替换操作占用cpu时间片。但是当业务中包含多个线程竞争一个锁时,就不适合使用偏向锁了。

而且调用一个对象的hashcode()方法会撤销该对象的偏向锁,将该对象的线程id信息替换为该对象的hashcode,是因为对象头没空间存储才撤销。轻量级锁和重量级锁都是与栈帧的锁记录进行交换的,所以不存在没空间存储的问题,调用他的hashcode方法当然也不会撤销轻量级锁或者重量级锁。

-XX:-useBiasedLocking表示禁用偏向锁,-XX:+useBiasedLocking表示开启偏向锁。

偏向锁撤销: 其他线程竞争时,会从偏向锁升级为轻量级锁。

锁消除:默认是打开的,使用-X:-elimiteLocks取消锁消除。jit会对代码进行逃逸分享,即使你加锁了,在发现该锁没有可能被多线程使用的情况会自动消除该锁。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表