当前位置: 首页 > news >正文

《锁侠闯江湖:小白通关Java synchronized底层秘境》

想象一下,你写的Java代码就是一个繁华的"对象城"。城里有很多"线程大侠"(Thread),他们武艺高强,飞檐走壁。但问题来了,城里有一个藏宝阁(共享资源),里面放着绝世珍宝——一个叫做 count 的变量。

如果所有大侠一拥而入,你抢我夺,count 的值就会错乱,江湖大乱。

这时,就需要一位 "锁侠"(synchronized)来守护藏宝阁,维持秩序。


第一幕:初入江湖——锁的三种招式

锁侠有三种不同的形态,对应不同的江湖场景:

招式一:招式锁(同步方法)

public synchronized void addCount() {count++;
}

这就像给整个藏宝阁大门加锁,一次只允许一位大侠进入。

招式二:兵器锁(同步代码块)

public void addCount() {synchronized(this) { // "this"就是这把锁的兵器count++;}
}

更灵活,只锁藏宝阁里最重要的那个宝箱,而不是整个大厅。

招式三:门派锁(同步类对象)

public static synchronized void staticMethod() {// ...
}

这锁的是整个"门派"(Class对象),所有这个门派的弟子(实例)都受此锁约束。

小白问:这些招式有什么区别?

  • 招式锁:锁的是当前实例对象(this

  • 门派锁:锁的是类的Class对象

  • 兵器锁:最灵活,可以指定任意对象作为"锁"


第二幕:锁的进化论——从少年到宗师

这才是最精彩的部分!锁侠不是生来就那么强大的,他经历了四次进化:

阶段一:无锁状态(Lockless)

  • 刚出道的锁侠,藏宝阁谁都能进,一片混乱

  • 适用于:线程安全的对象(如只读对象)

阶段二:偏向锁(Biased Locking) - "我的地盘我做主"

  • 故事:第一个来到藏宝阁的大侠A,锁侠说:"好吧,我看你面善,以后这锁就偏向你了!"

  • 原理:在对象头的Mark Word中记录线程ID,以后这个大侠A再来,直接放行,无需任何检查

  • 目的:在几乎没有竞争的场景下,消除同步开销

  • 触发条件:只有一个线程访问同步块

阶段三:轻量级锁(Lightweight Locking) - "文斗不武斗"

  • 故事:大侠B也来了!"等等,这里已经有人了!"但两位大侠都很文明,决定通过 CAS(Compare And Swap) 这种"文斗"方式竞争

  • 原理:在各线程的栈帧中创建锁记录(Lock Record),通过CAS操作尝试将对象头指向自己的锁记录

  • 特点:线程不会阻塞,通过自旋等待

  • 触发条件:多个线程交替执行,没有真正的同时竞争

阶段四:重量级锁(Heavyweight Locking) - "惊动朝廷"

  • 故事:大侠C、D、E...都来了!文斗解决不了,只能请出朝廷的 "Monitor(管程)" 来维持秩序

  • 原理:线程进入阻塞状态,放入等待队列,等待操作系统调度

  • 特点:真正的互斥,开销最大

  • 触发条件:多线程激烈竞争


第三幕:锁的内心世界——对象头探秘(详细注释版)

每个Java对象(藏宝阁)都有个 对象头(Object Header),就像身份证一样记录着锁的状态。在64位JVM中,对象头长这样:

Mark Word就是锁状态的"身份证",不同锁状态下它的结构完全不同:

1. 无锁状态(刚创建的对象)

详细解释:

  • identity_hashcode(31位):对象的哈希码,用于HashMap等

  • age(4位):对象的分代年龄(用于垃圾回收,最大15)

  • biased_lock(1位):偏向锁标志,0表示未启用偏向锁

  • lock(2位):锁标志位,01表示无锁状态

2. 偏向锁(第一个线程访问时)

详细解释:

  • thread(54位):持有偏向锁的线程ID

  • epoch(2位):偏向时间戳,用于批量撤销偏向锁

  • biased_lock(1位):偏向锁标志,1表示启用偏向锁

  • lock(2位):锁标志位,01与无锁状态相同,靠biased_lock区分

3. 轻量级锁(有竞争但不太激烈)

详细解释:

  • ptr_to_lock_record(62位):指向线程栈帧中锁记录的指针

  • lock(2位):锁标志位,00表示轻量级锁

4. 重量级锁(竞争激烈时)

详细解释:

  • ptr_to_heavyweight_monitor(62位):指向重量级锁Monitor对象的指针

  • lock(2位):锁标志位,10表示重量级锁

锁标志位总结表

锁状态biased_locklock说明
无锁001刚创建的对象
偏向锁101第一个线程访问
轻量级锁-00有竞争但不太激烈
重量级锁-10竞争激烈
GC标记-11对象被GC标记

关键洞察:看到这个表格了吗?JVM就是通过检查biased_locklock这两个标志位来判断当前对象的锁状态的!这就是锁升级的"密码本"。


第四幕:终极武器——Monitor管程

重量级锁的核心就是Monitor,可以把它想象成一个智能门禁系统

ObjectMonitor() {_header       = NULL;_count        = 0;      // 重入次数_waiters      = 0,      // 等待线程数_recursions   = 0;      // 锁的重入次数_object       = NULL;_owner        = NULL;   // 当前持有锁的线程_WaitSet      = NULL;   // 处于wait状态的线程队列_WaitSetLock  = 0 ;_EntryList    = NULL ;  // 处于等待锁block状态的线程队列
}

工作流程

  1. 线程尝试通过CAS获取锁,成功则成为 _owner

  2. 失败则进入 _EntryList 等待

  3. 获得锁的线程调用 wait() 时,释放锁并进入 _WaitSet

  4. 当其他线程调用 notify() 时,_WaitSet 中的线程被移到 _EntryList 重新竞争


第五幕:完整通关秘籍——锁升级流程图


最终决战:锁的选择策略

偏向锁:Java 15+ 默认禁用,因为维护成本高
轻量级锁:适用于短时间、低竞争的同步
重量级锁:高并发场景的最终选择

现代最佳实践

// 对于高并发场景,往往直接使用更高级的并发工具
private final AtomicInteger count = new AtomicInteger(0);public void addCount() {count.incrementAndGet(); // CAS操作,比synchronized更轻量
}

闯关成功总结

  1. synchronized不是一成不变的 - 它会根据竞争情况智能升级

  2. 锁的代价从低到高:无锁 → 偏向锁 → 轻量级锁 → 重量级锁

  3. 对象头是锁状态的记录者 - Mark Word的变化就是锁的进化史

  4. Monitor是最终的守护者 - 通过队列管理阻塞线程

现在,当你在代码中写下 synchronized 时,脑海中应该浮现出这幅完整的锁侠进化图。恭喜你,已经从 synchronized 小白晋级为锁原理高手!

记住:理解底层,是为了写出更好的上层代码! 🚀

http://www.dtcms.com/a/529071.html

相关文章:

  • 广州网站制作公司排名寿光网站优化
  • Python如何写Selenium全攻略
  • 【大模型的原理 - 从输入到输出】Transformer 的 Decoder-only 架构
  • 网站建设前置审批网站配色主题
  • 服务器pdb断点调试
  • 一次方的高阶无穷小 = 一次方 × 无穷小
  • 网站建设请款报告广东建设工程信息网官网首页
  • 【力扣hot100】238.除自身以外数组的乘积
  • 江门网站关键词推广seo关键词优化软件合作
  • 如何解决 pip install 安装报错 Backend ‘setuptools.build_meta’ 不可用 问题
  • C++智能指针使用指南(auto_ptr, unique_ptr, shared_ptr, weak_ptr)
  • GitHub等平台形成的开源文化正在重塑知可以谈人
  • 计算机网络:知识点梳理及讲解(三)数据链路层
  • PySide6 pyside6-deploy 命令 Linux 部署
  • 网站内的搜索怎么做的学校网站建设情况报告
  • 电脑建立网站朝阳区手机网站建设服务
  • 谷歌商店下载APK教程,先下载谷歌三件套,再直接从 Google Play 下载 APK 文件?
  • Spring中事务的传播行为
  • 将镜像推送到 Docker Hub 或私有仓库
  • 做qq图片的网站吗wordpress没有链接地址
  • 面向模块的综合技术之重定时优化(六)
  • 社交模板网站建设成都青羊网站建设
  • Android 数据持久化(SharedPreferences)
  • 四、高效注意力机制与模型架构
  • 沧州做网站公司兰州网站建站
  • C++ STL:string类(1) |了解string|编码|常用接口|迭代器|算法查找|auto|范围for
  • ESP32 Linux 开发环境
  • 网站建设全国排名alexa排名前三十
  • 声乐基础知识学习
  • Redis底层原理-持久化【详细易懂】