Java并发编程——锁升级机制
- 软件开发
- 2025-09-03 13:45:01

在 Java 的并发编程世界里,锁机制是保障多线程安全的关键手段。Java SE 1.6为了减少获得锁和释放锁带来的性能消耗,引入了“偏向锁”和“轻量级锁”,在 Java SE 1.6中,锁一共有4种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状 态和重量级锁状态,这几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级,意味着偏 向锁升级成轻量级锁后不能降级成偏向锁。
无锁(No Lock)适用场景:对象未被任何线程访问,或仅被单个线程无竞争访问。
对象头标记:无锁状态的对象头中,Mark Word的锁标志位为001。
性能特点:完全无同步操作,访问速度最快。
偏向锁(Biased Lock)当第一个线程访问 synchronized 修饰的代码块时,JVM 会在对象头中记录下这个线程的 ID,此时对象进入偏向锁状态。偏向锁的设计理念是,如果一个锁总是被同一个线程访问,那么为该线程省去每次获取锁的开销,直接进入同步代码块
设计目标:优化单线程重复加锁的场景(如循环内的同步操作)。
实现机制:
对象头记录偏向线程ID(Thread ID)与时间戳(Epoch)。
线程首次获取锁时,通过CAS将线程ID写入对象头,后续可直接访问。
升级触发条件:
其他线程尝试获取锁时,JVM撤销偏向锁(Revoke Bias),并检查原线程是否存活。
若原线程已结束,对象可重新偏向新线程;否则升级为轻量级锁。
JDK 15后的变化:默认禁用偏向锁(-XX:-UseBiasedLocking),因其撤销操作在高并发场景可能引入额外开销。
轻量级锁(Lightweight Lock)当有第二个线程尝试访问同一个 synchronized 代码块时,偏向锁就无法满足需求了,此时锁会升级为轻量级锁。轻量级锁采用 CAS(Compare - And - Swap,比较并交换)操作来尝试获取锁。
JVM 会在线程的栈帧中创建一个锁记录(Lock Record),并将对象头中的 Mark Word 复制到锁记录中。然后,线程尝试使用 CAS 将对象头中的 Mark Word 更新为指向锁记录的指针。如果更新成功,线程就获得了锁,可以进入同步代码块;如果更新失败,说明锁已经被其他线程持有,线程会进行自旋等待。自旋是指线程在一段时间内不放弃 CPU 资源,不断尝试获取锁,避免了线程上下文切换的开销。如果自旋一定次数后仍未获取到锁,轻量级锁就会升级为重量级锁。
适用场景:多线程交替执行但无实际竞争(如短时并发)。
实现机制:
线程在栈帧中创建锁记录(Lock Record),将对象头Mark Word复制到锁记录。
通过CAS将对象头指向锁记录,若成功则获取锁;失败则自旋重试或升级锁。
自旋优化:JVM采用适应性自旋(Adaptive Spinning),动态调整自旋次数。
升级触发条件:
自旋超过阈值(默认10次,可通过-XX:PreBlockSpin调整)。
竞争线程数超过1个,升级为重量级锁。
重量级锁(Heavyweight Lock)当多个线程竞争激烈,轻量级锁自旋多次后仍无法获取锁时,就会升级为重量级锁。重量级锁依赖于操作系统的互斥量(Mutex)来实现,当一个线程获取到重量级锁后,其他未获取到锁的线程会被阻塞,进入内核态等待。这种方式会带来较大的性能开销,因为线程的阻塞和唤醒需要进行用户态和内核态的切换。
实现原理:依赖操作系统互斥量(Mutex)和条件变量(Condition Variable)。
性能影响:
线程竞争时进入阻塞状态,涉及用户态到内核态的切换,开销最大。
支持公平锁与非公平锁策略,通过等待队列管理线程调度。
锁类型适用场景吞吐量延迟无锁无竞争最高最低偏向锁单线程重复访问高低轻量级锁低竞争短时并发中中重量级锁高竞争长时阻塞低高 锁升级机制的局限性偏向锁的权衡:
虽然减少了单线程开销,但撤销操作可能导致“锁冷启动”问题。
JDK 15后默认禁用,开发者需评估是否手动启用。
自旋的资源消耗:
长时间自旋会占用CPU资源,需结合适应性自旋策略。不可逆升级:
一旦升级为重量级锁,无法回退到轻量级锁。Java并发编程——锁升级机制由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Java并发编程——锁升级机制”
上一篇
【NLP25、模型训练方式】
下一篇
算法日常刷题笔记(1)