持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情
深入学习synchronized锁升级
相信各位java方向的选手们对于synchronized锁应该都非常熟悉了吧,那咱们今天就一起来学习一下 锁升级 的具体内容。
前言
我们都知道加锁是会影响系统的并发度的,而synchronized更是重量级锁,它是同步的,会在很大程度上影响性能,需要可以有一些锁细化等的锁优化理论,但是还是尽量能不加锁就不加锁。
也正因为如此,才提出了 锁升级 的概念。
锁升级的具体过程
在讲锁升级之前,我们需要先来了解一下对象头。
在Hotspot虚拟机中,java对象头中有这么两个标志位:
如果是给某个对象上锁了之后,就会在对应的对象头上的标志位上做好标志。
无锁
这是一个最自然的状态了,对象的最初都是无锁状态的,这时候的具体标志位值如上图所示。
偏向锁
如果某个资源只有一个线程来访问,那这种情况下完全不需要加锁,因为只有它自己一个线程来访问,压根不会有其他线程对它所需要访问的线程做出修改。
所以,在这种情况下,只是在对象头上更改一下标志位,但并未申请锁资源。
性能方面几乎和无锁一致!
自旋锁
上面说到了,在只有一个线程访问某个对象资源的时候,是只加了偏向锁(实际上是没有加锁的,只是在对象头的标志位上做了标志);但是如果此时有别的线程也来访问这个对象资源了呢?
这时候也不是一上来就加重量级锁的,首先新来的线程会自旋(在CPU里空转,什么也没有执行,不断地在问某某某资源好了吗?空闲了吗?)
如果刚好偏向锁被释放了,那么新来的线程就可以直接访问该对象资源了;如果新来的线程自旋了多次(10次),偏向锁还没有释放,那么这时候,锁就会升级为重量级锁(向操作系统申请),而与此同时,新来的线程也就无法继续待在CPU里了,它被带进了等待队列里。
重量级锁
并发度是最低的,影响性能最大的。
注意:锁升级之后是无法降级的!