说一下synchronized锁升级过程
-
偏向锁 在 JDK1.8 中,其实默认是轻量级锁,但如果设定了 -XX:BiasedLockingStartupDelay = 0 ,那在对一个 Object 做 syncronized 的时候,会立即上一把偏向锁。当处于偏向锁 状态时, markwork 会记录当前线程 ID 。
-
升级到轻量级锁 当下一个线程参与到偏向锁竞争时,会先判断 markword 中保存的线程 ID 是否与这个 线程 ID 相等,如果不相等,会立即撤销偏向锁,升级为轻量级锁。每个线程在自己的线 程栈中生成一个 LockRecord ( LR ),然后每个线程通过 CAS (自旋)的操作将锁对象头 中的 markwork 设置为指向自己的 LR 的指针,哪个线程设置成功,就意味着获得锁。 关于 synchronized 中此时执行的 CAS 操作是通过 native 的调用 HotSpot 中 bytecodeInterpreter.cpp 文件 C++ 代码实现的,有兴趣的可以继续深挖。
-
升级到重量级锁 如果锁竞争加剧(如线程自旋次数或者自旋的线程数超过某阈值, JDK1.6 之后,由 JVM 自己控制该规则),就会升级为重量级锁。此时就会向操作系统申请资源,线程挂起,进 入到操作系统内核态的等待队列中,等待操作系统调度,然后映射回用户态。在重量级 锁中,由于需要做内核态到用户态的转换,而这个过程中需要消耗较多时间,也就 是"重"的原因之一。