synchronized锁的四种状态和锁升级过程笔记

synchronized从jdk1.6开始引入了偏向锁和轻量级锁,作为无锁和重量级锁的中间状态。
锁随着竞争情况加剧逐渐升级,锁可以从偏向锁升级到轻量级锁,再升级到重量级锁,只能升级不能降级。注意无锁状态就是没有锁。
在这里插入图片描述
无锁时存储对象的hashcode、对象的分代年龄、是否为偏向锁的标志(0表示不是偏向锁),无锁的标志位是01;
当有一个线程访问同步块时无锁就要升级为偏向锁,偏向锁存储内容为偏向线程ID、偏向时间戳、对象分代年龄、是否偏向锁(1),它的标志位和无锁相同,都是01;
当有锁竞争时,也就是并发情况出现的时候,就升级为轻量级锁,而在锁竞争不激烈时,没有竞争到锁的线程自旋等待持有锁的线程释放锁,因此轻量级锁也叫自旋锁,当自旋十次失败,轻量级锁就会升级为重量级锁而阻塞。
轻量级锁存储内容为指向栈中锁的记录的指针,标志位时00;重量级锁存储的则是指向互斥量的指针,标志位时11.

对比
偏向锁的加锁和解锁不需要额外的消耗,和执行非同步方法相比只存在纳秒级的差距,但如果线程间存在锁竞争,会带来锁撤销的消耗(竞争的线程试图用CAS修改偏向锁线程ID时失败,说明持有偏向锁的线程还在运行,这时就进入了偏向锁撤销的过程),因此偏向锁适用于只有一个线程访问同步块的情况;
轻量级锁竞争的线程不会阻塞,没获取到锁的线程处于自旋等待的状态,提高了响应速度,但如果线程自旋时间太长就会浪费CPU,因为自旋实际上就是在循环检测锁是否释放来等待;
重量级锁则是在锁竞争时令线程阻塞,因此响应时间缓慢,适用于锁竞争激烈的场景,比如追求吞吐量的时候。

补充
获取锁的过程就是通过CAS修改锁的对象头里的锁标志位,锁是一个对象。
synchronized使用的锁存在Java锁对象头的Mark Word中,以hotspot虚拟机为例,hotspot对象头包含两部分数据: Mark word(标记字段) 和Class Pointer(类型指针)。Mark word存储对象的hashCode、分代年龄和锁标志位信息。这些信息都是与对象自身定义无关的数据,所以Mark word被设计成非固定的数据结构以便在极小空间内存储更多的数据,在运行期间其数据会随着锁标志位的变化而变化。
Class Pointer是对象指向它的元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
在这里插入图片描述
每一个Java对象都有内部锁或者说Monitor锁。Monitor是线程私有的数据结构。每个被锁住的对象(从后面可知,monitor通过互斥锁实现,互斥锁需要操作系统状态转换,因此这里的被锁住似乎是指的被重量级锁锁住? )都会和一个monitor关联,同时monitor中有一个Owner字段存放拥有该锁的线程的唯一标识(这个和偏向锁的偏向线程ID似乎不是一个东西?否则偏向锁要是使用了monitor岂不是成了重量锁了?),表示该锁被此线程占用。
synchronized的重量级锁是通过对象内部的监视器锁monitor来实现的,监视器锁本身又依赖底层操作系统的Mutex Lock(互斥锁)来实现,而操作系统实现线程之间的切换需要从用户态转换到核心态,状态转换很耗时,因此重量级锁效率低。依赖于操作系统mutex lock的锁就叫重量级锁。

无锁就是没有对资源进行锁定,当一个线程执行到synchronized代码块时,CAS修改锁标志位变成偏向锁(理解为偏向于第一个获得它的线程的锁),执行完同步代码后,线程不会主动释放偏向锁,当第二次到达同步块,线程会判断此时持有该锁的线程是否是自己(锁的线程id在它的对象头里),若是则正常往下执行,不需要重新加锁。如果自始至终使用锁的线程只有一个,偏向锁几乎没有额外开销,性能很好。
当一个线程访问同步代码获取到锁时,会在锁的Mark word里存储该锁偏向的线程ID,在线程进入和退出同步块时不再通过CAS来加锁和解锁,而是检测锁对象的mark word里的偏向的线程ID,所以偏向锁只依赖最开始的一次CAS操作。

偏向锁的撤销(不太懂)

偏向锁使用了一种等到竞争出现才释放锁的机制,所以当其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁。偏向锁的撤销,需要等待全局安全点(在这个时间点上没有字节码正在执行),它会首先暂停拥有偏向锁的线程,然后检查持有偏向锁的线程是否活着,如果线程不处于活动状态,则将对象头设置成无锁状态,如果线程仍然活着,拥有偏向锁的栈会被执行,遍历偏向对象的锁记录,栈中的锁记录和对象头的Mark Word,要么重新偏向于其他线程,要么恢复到无锁或者标记对象不适合作为偏向锁,最后唤醒暂停的线程。

完整原理:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值