synchronized 锁升级

简介: JDK 6 引入的 synchronized 锁升级机制,通过偏向锁、轻量级锁和重量级锁的动态切换,优化了多线程同步性能。该机制根据竞争情况逐步升级锁状态,减少线程阻塞和系统调用开销,从而提升并发效率。

synchronized 锁升级是 JDK 6 引入的重要优化,通过偏向锁、轻量级锁、重量级锁的逐步升级策略,减少了传统重量级锁的性能开销。以下是锁升级的详细过程和原理:

1. 锁升级的核心动机

  • 传统重量级锁的问题:依赖操作系统的互斥量(Mutex)实现,线程阻塞和唤醒需从用户态切换到内核态,性能损耗大。
  • 优化思路:根据实际场景动态调整锁的粒度,避免不必要的重量级锁开销。

2. 锁状态与对象头

每个 Java 对象的对象头(Mark Word)中存储着锁状态信息,不同状态下 Mark Word 的结构如下:

锁状态 存储内容 标志位
无锁 对象哈希码、分代年龄 01
偏向锁 线程 ID、Epoch、分代年龄 01
轻量级锁 指向线程栈中锁记录的指针 00
重量级锁 指向 Monitor 的指针 10
GC 标记 11

3. 锁升级的具体过程

(1)偏向锁(Biased Locking)

  • 适用场景:只有一个线程访问同步块,无竞争。
  • 获取过程
    1. 当第一个线程 T1 访问同步块时,JVM 通过 CAS 操作将线程 ID 写入 Mark Word,同时将标志位设为 01(偏向锁)。
    2. 后续 T1 再次进入同步块时,无需任何同步操作,直接判断 Mark Word 中的线程 ID 是否为自己,若是则直接执行。
  • 撤销过程
    1. 当有其他线程 T2 尝试竞争该锁时,T1 会被暂停,JVM 检查 T1 是否仍在执行同步块:
      • 若已退出:Mark Word 恢复为无锁状态,T2 可竞争并获取偏向锁。
      • 若仍在执行:偏向锁升级为轻量级锁,T1 继续执行,T2 自旋等待。
  • 批量重偏向与撤销
    • 当一个类的对象频繁发生偏向锁撤销时,JVM 会认为该类不适合偏向锁,批量将该类的对象偏向锁撤销或禁用。

(2)轻量级锁(Lightweight Lock)

  • 适用场景:多个线程交替访问同步块,无实际竞争。
  • 加锁过程
    1. 线程进入同步块前,在当前线程的栈帧中创建锁记录(Lock Record),并将 Mark Word 复制到锁记录中(Displaced Mark Word)。
    2. 通过 CAS 尝试将 Mark Word 更新为指向锁记录的指针:
      • 成功:获取轻量级锁,Mark Word 标志位变为 00
      • 失败:表示有其他线程竞争,锁升级为重量级锁。
  • 解锁过程
    1. 通过 CAS 将锁记录中的 Displaced Mark Word 替换回 Mark Word。
    2. 若替换成功:锁释放完成。
    3. 若替换失败:表示有其他线程在竞争,已升级为重量级锁,需唤醒被阻塞的线程。

(3)重量级锁(Heavyweight Lock)

  • 适用场景:多个线程同时竞争锁。
  • 升级过程
    1. 当轻量级锁竞争失败时,锁升级为重量级锁,Mark Word 存储指向 Monitor 的指针,标志位变为 10
    2. 未获取到锁的线程会被阻塞(进入 Monitor 的 EntryList),释放 CPU 资源。
  • 释放过程
    1. 持有锁的线程执行完同步块后,释放 Monitor。
    2. 唤醒 EntryList 中的线程重新竞争。

4. 锁升级的流程图

无锁状态 → 偏向锁(单线程) → 轻量级锁(多线程交替) → 重量级锁(多线程竞争)

5. 锁升级的关键点

  • 不可逆性:锁只能升级,不能降级(但偏向锁可撤销为无锁)。
  • 自旋锁(Spin Lock):轻量级锁竞争时,线程会短暂自旋等待锁释放,避免直接阻塞(JDK 6 后自旋次数可自适应)。
  • 锁粗化(Lock Coarsening):JVM 会将多个连续的加锁、解锁操作合并为一个,减少锁的获取和释放次数。
  • 锁消除(Lock Elimination):对不可能存在共享资源竞争的锁进行消除(如局部变量锁)。

6. 性能对比

锁类型 优点 缺点 适用场景
偏向锁 无同步开销,单线程性能极佳 存在锁撤销开销 单线程访问同步块
轻量级锁 竞争不激烈时避免线程阻塞 自旋消耗 CPU 多线程交替访问
重量级锁 保证线程安全,处理高竞争场景 线程阻塞和唤醒开销大 多线程同时竞争

7. 优化建议

  • 减少锁竞争:通过减小锁粒度、缩短锁持有时间降低竞争。
  • 批量偏向锁:对于频繁创建的对象,可通过 JVM 参数 -XX:+UseBiasedLocking 启用偏向锁。
  • 高并发场景:考虑使用 ReentrantLockConcurrentHashMap 等更灵活的同步工具。

总结

锁升级机制通过动态调整锁的状态,在不同场景下平衡了性能和线程安全:

  • 偏向锁:优化单线程场景,几乎无同步开销。
  • 轻量级锁:处理多线程交替访问,避免内核态切换。
  • 重量级锁:应对高竞争场景,保证线程安全。

理解锁升级原理有助于写出更高效的多线程代码,避免不必要的性能损耗。

目录
相关文章
|
12月前
|
安全
一文搞懂synchronized锁的升级过程
synchronized锁的升级过程包括偏向锁、轻量锁和重量级锁。偏向锁在无竞争时可重复使用,轻量锁通过CAS自旋实现多线程竞争,重量级锁则会导致线程阻塞,涉及用户态到内核态的切换。CAS(比较并交换)用于实现乐观锁,保证原子性操作,但可能引发CPU资源浪费。文中还展示了手写锁的升级实现代码。
568 0
【面试问题】Synchronized 和 ReentrantLock 区别?
【1月更文挑战第27天】【面试问题】Synchronized 和 ReentrantLock 区别?
|
缓存 Java 应用服务中间件
Tomcat是如何打破"双亲委派"机制的?
上文我们详细了解了类加载以及什么是双亲委派机制,相信很多童鞋都了解Tomcat打破了双亲委派机制,本文将对Tomcat为什么要打破双亲委派机制,以及Tomcat是如何打破双亲委派机制的,进行完整性的复盘与解析。
4250 0
Tomcat是如何打破"双亲委派"机制的?
|
Java
G1垃圾回收器的工作流程
G1垃圾回收器的工作流程
2498 0
|
5月前
|
存储 安全 Java
深入拆解 synchronized:从偏向锁到重量级锁的升级之旅与优化秘籍
本文深入剖析Java中synchronized的底层实现:详解偏向锁、轻量级锁到重量级锁的升级机制,结合对象头Mark Word结构、JVM锁优化(自旋、消除、粗化、逃逸分析),并附死锁排查实战,助你真正掌握并发同步原理。
294 3
|
Java 存储
线程池的核心参数有哪些?
线程池七大核心参数:核心/最大线程数、线程保持时间及单位、阻塞队列、线程工厂与拒绝策略。
1788 79
|
11月前
|
消息中间件 监控 Kubernetes
别再乱排查了!Kafka 消息积压、重复、丢失,根源基本都是 Rebalance!
大家好,我是小富~分享一次Kafka消息积压排查经历:消费者组因Rebalance导致消费能力骤降。本文详解Rebalance触发场景(消费者变更、分区扩容、订阅变化、超时等),剖析其引发的消息积压、重复消费、丢失等问题根源,并提供优化方案:调优超时参数、手动提交offset、启用粘性分配策略、保障消费幂等性。掌握这些,轻松应对Kafka常见故障!
1957 0
|
存储 缓存 人工智能
【原理】【Java并发】【synchronized】适合中学者体质的synchronized原理
本文深入解析了Java中`synchronized`关键字的底层原理,从代码块与方法修饰的区别到锁升级机制,内容详尽。通过`monitorenter`和`monitorexit`指令,阐述了`synchronized`实现原子性、有序性和可见性的原理。同时,详细分析了锁升级流程:无锁 → 偏向锁 → 轻量级锁 → 重量级锁,结合对象头`MarkWord`的变化,揭示JVM优化锁性能的策略。此外,还探讨了Monitor的内部结构及线程竞争锁的过程,并介绍了锁消除与锁粗化等优化手段。最后,结合实际案例,帮助读者全面理解`synchronized`在并发编程中的作用与细节。
1127 8
【原理】【Java并发】【synchronized】适合中学者体质的synchronized原理
|
关系型数据库 数据库 索引
间隙锁
间隙锁是数据库中用于解决幻读问题的锁机制,主要在可重复读隔离级别下生效。它通过锁定索引记录之间的间隙,阻止其他事务插入新数据,从而保证查询结果的一致性。间隙锁在范围查询、唯一索引不存在记录时等场景触发,既能防止并发插入冲突,也可能降低并发性能并引发死锁。合理配置隔离级别和优化查询条件可减少其影响。
611 0
|
消息中间件 算法 调度
分布式系统学习10:分布式事务
本文是小卷关于分布式系统架构学习系列的第13篇,重点探讨了分布式事务的相关知识。随着业务增长,单体架构拆分为微服务后,传统的本地事务无法满足需求,因此需要引入分布式事务来保证数据一致性。文中详细介绍了分布式事务的必要性、实现方案及其优缺点,包括刚性事务(如2PC、3PC)和柔性事务(如TCC、Saga、本地消息表、MQ事务、最大努力通知)。同时,还介绍了Seata框架作为开源的分布式事务解决方案,提供了多种事务模式,简化了分布式事务的实现。
843 5

热门文章

最新文章