从0到1带你深入并发编程002:锁会从用户态走向内核态-synchronized底层揭秘-Java对象锁的进化史:偏向锁→轻量级锁→重量级锁的智慧

编程达人挑战赛·第3期 10w+人浏览 288人参与

🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐➕关注👀是作者创作的最大动力🤞

💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝+关注👀欢迎留言讨论

🔥🔥🔥(源码获取 + 调试运行 + 问题答疑)🔥🔥🔥  有兴趣可以联系我

🔥🔥🔥  文末有往期免费源码,直接领取获取(无删减,无套路)

我们常常在当下感到时间慢,觉得未来遥远,但一旦回头看,时间已经悄然流逝。对于未来,尽管如此,也应该保持一种从容的态度,相信未来仍有许多可能性等待着我们。

《深入剖析synchronized:从对象头到重量级锁的完整升级路径》

《Java对象锁的进化史:偏向锁→轻量级锁→重量级锁的智慧》

《synchronized底层揭秘:为何你的锁会从用户态走向内核态?》


正文

一、对象锁:Java并发的基石

在Java并发编程的世界里,synchronized关键字作为最古老、最基础的同步机制,经历了二十多年的演进与优化。从最初的性能瓶颈到如今的高度优化,对象锁的实现原理体现了JVM开发者在性能与功能之间的精妙平衡。

每个Java对象都与一个内置锁(monitor)相关联,这个锁的实现并非一成不变,而是根据竞争情况动态调整。理解这个动态过程,对于编写高性能的并发程序至关重要。

二、对象头:锁信息的存储中心

要理解synchronized的工作原理,首先需要了解Java对象的内存布局。每个对象在堆中都包含三个部分:对象头、实例数据和对齐填充。其中,对象头是锁机制的核心载体。

对象头的组成:

  • Mark Word(标记字):存储对象的哈希码、GC分代年龄、锁状态等信息

  • Klass Pointer(类型指针):指向对象所属的类元数据

  • 数组长度(仅数组对象):记录数组的长度

Mark Word在不同锁状态下会存储不同的内容,这种复用设计体现了极致的空间优化思想。

三、Mark Word的结构演变

Mark Word在32位和64位JVM中的结构有所不同,但其设计理念一致:用最小的空间存储最多的信息。

32位JVM的Mark Word布局:

锁状态25位4位1位(偏向锁标志)2位(锁标志)
无锁对象的hashCode分代年龄001
偏向锁线程ID + Epoch分代年龄101
轻量级锁指向栈中锁记录的指针--00
重量级锁指向互斥量(monitor)的指针--10
GC标记--11

这种设计使得JVM能够在运行时根据锁状态动态解释Mark Word的含义,实现了极致的空间利用率。

四、锁升级:智能的优化策略

锁升级(锁膨胀)是synchronized性能优化的核心策略。JVM并不是一开始就使用重量级锁,而是根据竞争情况逐步升级,这个过程完全自动且对开发者透明。

4.1 偏向锁(Biased Locking)

适用场景:实际上没有竞争或只有一个线程使用的场景

偏向锁的核心理念是"偏向第一个访问的线程"。当线程第一次获得锁时,JVM会在对象头和栈帧中记录偏向的线程ID。之后该线程再次进入同步块时,不需要进行CAS操作,只需简单检查对象头的线程ID是否匹配。

偏向锁的获取流程:

  1. 检查Mark Word中的偏向锁标志和线程ID

  2. 如果可偏向且线程ID匹配,直接进入同步块

  3. 如果未偏向,通过CAS竞争偏向锁

  4. 如果已偏向但线程ID不匹配,开始撤销偏向锁

偏向锁的引入基于这样一个观察:在大多数应用中,锁在大部分时间内不会被多个线程竞争。

4.2 轻量级锁(Lightweight Locking)

当偏向锁被撤销后,锁会升级为轻量级锁。轻量级锁的核心思想是:在没有真实竞争的情况下,通过CAS操作避免操作系统的互斥操作。

轻量级锁的加锁过程:

  1. 在当前线程的栈帧中创建锁记录(Lock Record)

  2. 将对象头的Mark Word复制到锁记录中(Displaced Mark Word)

  3. 使用CAS将对象头的Mark Word替换为指向锁记录的指针

  4. 如果CAS成功,当前线程获得锁

  5. 如果CAS失败,说明存在竞争,开始自旋或升级

轻量级锁的"轻量"体现在它避免了用户态到内核态的切换,所有操作都在用户空间完成。

4.3 自旋优化

在轻量级锁竞争失败后,线程不会立即挂起,而是进行自旋等待。自旋的本质是让线程执行一个忙循环,期待在短时间内锁能被释放。

自旋策略的演进:

  • 早期:固定次数自旋(如10次)

  • 现在:自适应自旋(根据上次自旋成功情况动态调整)

自适应自旋是JVM智能化的体现:如果某个锁上次自旋成功获得了锁,那么这次会允许更长的自旋时间;反之,则减少自旋甚至直接升级。

4.4 重量级锁(Heavyweight Locking)

当轻量级锁自旋失败后,锁最终会升级为重量级锁。重量级锁基于操作系统的互斥量(mutex)实现,涉及用户态到内核态的切换。

重量级锁的核心组件:

  • ObjectMonitor:JVM层的monitor对象

  • cxq:竞争队列,存储等待锁的线程

  • EntryList:入口队列

  • WaitSet:等待队列(调用wait()的线程)

重量级锁的加锁过程涉及内核态操作,线程上下文切换开销较大,但能够正确处理复杂的竞争场景。

五、锁升级的触发条件

理解锁升级的触发条件对于性能调优至关重要:

偏向锁→轻量级锁:当有第二个线程尝试获取锁时 轻量级锁→重量级锁:自旋失败或等待线程数超过阈值 直接重量级锁:调用了wait()、notify()等方法

六、重量级锁的底层实现

重量级锁的实现依赖于ObjectMonitor对象,其核心方法包括:

 class ObjectMonitor {
     void* volatile _owner;          // 当前持有锁的线程
     ObjectWaiter* volatile _cxq;    // 竞争队列
     ObjectWaiter* volatile _EntryList; // 入口队列
     ObjectWaiter* volatile _WaitSet;   // 等待队列
     volatile int _recursions;       // 重入次数
     // ...
 };

当线程尝试获取重量级锁时:

  1. 通过CAS尝试设置_owner字段

  2. 如果失败,进入cxq队列等待

  3. 等待期间线程被挂起,进入内核态阻塞

  4. 锁释放时,从队列中唤醒等待线程

七、锁升级的目的与价值

锁升级策略体现了JVM在性能优化上的深度思考:

1. 性能与功能的平衡

  • 无竞争时:偏向锁,几乎零开销

  • 轻度竞争:轻量级锁,用户态CAS

  • 激烈竞争:重量级锁,保证正确性

2. 适应真实场景 大多数应用中的锁竞争都是短暂的,升级策略适应了这种"局部性"特征。

3. 避免过度优化 重量级锁虽然开销大,但在高竞争下比持续自旋更有效。

八、synchronized vs AQS实现的锁

虽然都是锁实现,但synchronized和AQS在设计和适用场景上存在显著差异:

特性synchronizedAQS实现的锁
实现方式JVM内置,自动优化Java代码,手动控制
锁升级自动完成,对开发者透明无自动升级,策略固定
灵活性相对固定高度可定制
功能特性基础同步支持条件队列、公平性等
性能特点低竞争下性能极佳高竞争下更可控
使用复杂度简单易用需要深入理解

九、实践建议与性能调优

基于对锁原理的理解,我们可以得出以下实践建议:

1. 减少锁竞争

  • 缩小同步代码块范围

  • 使用读写分离策略

  • 避免在锁内进行IO操作

2. 合理选择锁类型

  • 低竞争场景:优先synchronized

  • 高竞争或需要高级特性:考虑ReentrantLock

3. 监控锁状态 使用JVM参数监控锁升级情况:

 -XX:+PrintFlagsFinal | grep BiasedLocking
 -XX:+PrintSafepointStatistics

十、总结

synchronized的对象锁机制是Java并发设计的典范之作。从偏向锁到重量级锁的升级路径,体现了JVM开发者在性能优化上的深度思考。理解这个过程的每个细节,不仅有助于我们编写更高效的并发代码,更能让我们体会到系统设计中的平衡智慧。

在微服务和高并发成为主流的今天,虽然出现了更多新的并发工具,但synchronized凭借其简洁性和持续的优化,仍然是大多数场景下的首选同步机制。



「在线考试系统源码(含搭建教程)」 (无删减,无套路):🔥🔥🔥  

链接:https://pan.quark.cn/s/96c4f00fdb43 提取码:WR6M


往期免费源码对应视频:

免费获取--SpringBoot+Vue宠物商城网站系统

🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐➕关注👀是作者创作的最大动力🤞

💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝+关注👀欢迎留言讨论

🔥🔥🔥(源码 + 调试运行 + 问题答疑)

🔥🔥🔥  有兴趣可以联系我

💖学习知识需费心,
📕整理归纳更费神。
🎉源码免费人人喜,
🔥码农福利等你领!

💖常来我家多看看,
📕网址:扣棣编程
🎉感谢支持常陪伴,
🔥点赞关注别忘记!

💖山高路远坑又深,
📕大军纵横任驰奔,
🎉谁敢横刀立马行?
🔥唯有点赞+关注成!

⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇点击此处获取源码⬇⬇⬇⬇⬇⬇⬇⬇⬇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值