从字节码到对象头:synchronized 如何实现?

原文来自于:zha-ge.cn/java/90

从字节码到对象头:synchronized 如何实现?

昨天晚上,和几个朋友撸串,聊着聊着就跑题到 JVM 了(程序员聚会的经典套路)。喝了点啤酒,突然有人抛来一句:"你们真的懂 synchronized 怎么实现的吗?不是就是加个锁嘛,有啥难的。"我差点被辣椒呛到,哎呀,这话要是在网友面前说出来,分分钟被锤成铁渣!

其实,synchronized 的实现真没那么傻瓜,表面看着一个关键词,背后那套骚操作,多了去了。正好今天就顺着喝酒那点后劲,来一波随性的八卦,和你讲讲 synchronized 从 Java 源码,一路飞到字节码,从 HotSpot 的对象头里掏出那些暗藏的小心思。


synchronized 到底是什么玩意儿?

还记得刚入门的时候,我天真地以为 synchronized 就是把代码"包起来",线程就乖乖排队了。比如这样:

java 复制代码
synchronized (obj) {
    // 神奇的线程安全地带
}

每次用了 synchronized,总有种靠关键词发号施令的错觉。但后来我才发现,JVM 压根不惯着你,偷偷在背后做了好多事。


字节码揭底:"汇编级控制大法"

那天喝高了,回来翻 JVM 指令表,发现 synchronized 原来是变身成 monitorentermonitorexit 这俩指令的。哎,不看真不信:

java 复制代码
// 伪代码哈,其实 javap 看下就明白了
monitorenter
// 同步块的内容......
monitorexit

所以 synchronized 本质是"墩上锁"(monitorenter),走的时候"松开锁"(monitorexit)。关键是,锁不是凭空出来的------而是藏在对象头(object header)里。


对象头的秘密:Mark Word 的自我修养

对象头是什么?你想象成每个 Java 对象头顶都顶着块"砖头",这块砖里藏着很多秘密------Mark Word 就是最爱搞事情的那个。

Mark Word 里记录了锁的状态,比如:

  • 轻量级锁
  • 偏向锁
  • 重量级锁
  • 哈希码
  • 垃圾回收信息

不同的加锁方式,其实就是 Mark Word 换了种写法。拿锁其实就是 Mark Word 在变魔术------偏向锁、轻量级锁,最后不得不升级成咣咣互斥的大锁(重量级),才用到操作系统的 Mutex。


踩坑瞬间

别说,早期自己写多线程,还真翻过车。下面几件事,堪称"听我踩坑少走弯路"系列:

  • 升级锁的时候,发现性能突然闪崩。一查,原来竞争太激烈,锁直接升级为重量级,线程全都在那等队,场面一度失控。
  • synchronized 修饰方法和修饰代码块的区别。朋友好奇,method-level 和 block-level 有啥区别?一试,锁住对象还是锁住 class,可千万别搞混,不然 debug 吐血。
  • 分布式场景下误用 synchronized,哈哈,发现压根没啥卵用:JVM 内部锁,跨进程它不管!

JVM 的骚操作:"偏向锁"那些动静

其实 synchronized 在 HotSpot 下不是一上来就是大锁。JVM 精于算计,能"偏向"就不"加大锁",能"小打小闹"绝不"动手术":

  1. 偏向锁:一个线程拿了锁,后续只要别人不抢,JVM 就当做"你说了算",开小灶,几乎无开销。
  2. 轻量级锁:俩线程偶尔来点摩擦,JVM 就用 CAS(乐观锁)来做点小管理,性能还 OK。
  3. 重量级锁:真打起来了,甚至大家干脆都等着------这时候只好叫操作系统 Mutex。

这些升级/降级,完全靠 Mark Word 这一块砖反复雕花。


经验启示

踩过不少"锁"的坑,我个人现在有几条牢骚建议:

  • synchronized 虽暖心,但不要太迷信性能。"大面积锁"分分钟锤爆服务器。
  • 要理解背后的对象头和 JVM 操作,这样调优时才不抓瞎。
  • 并发编程不止有 synchronized,场景一多,建议多研究下 ReentrantLock、CAS 那些骚玩意儿。
  • 永远别指望 JVM 自己帮你搞定全部并发问题,分布式还得靠更高阶的锁。

写在最后

唉,说了这么多,synchronized 就是个看似"关键词",实则背后牵扯到字节码、对象头、Mark Word、锁升级的"大工程"。

很多初学者会觉得它就是个"铁门",进出靠排队。但你真把门板掀开,发现里面塞满了机关暗道:轻量级、偏向、重量级,能耍的花样一堆。

所以啊,synchronized 是好用,但不代表无脑用:

如果只是单线程逻辑或者无共享状态,完全没必要搞锁,反而多此一举。

在高并发场景,滥用 synchronized 就等于把高速公路硬生生改成单行线,拥堵那是必然的。

调优的时候别怕去看字节码、对象头、JVM 参数,很多玄学性能问题,其实都是 JVM 在背后偷偷搞小动作。

最后一句:理解 synchronized,不是为了炫技,而是让你写多线程代码时心里有底。不然真到线上出幺蛾子,你会怀疑人生。

相关推荐
硅基诗人1 分钟前
Java后端高并发核心瓶颈突破(JVM+并发+分布式底层实战)
java·jvm·分布式
聆听。。花开雨落8 分钟前
intelij idea闪退后再启动tomcat报错端口冲突
java·tomcat·intellij-idea
Java面试题总结9 分钟前
Spring Boot 包扫描新姿势:AutoScan vs @Import vs @ComponentScan 深度对比
java·数据库·spring boot
花千树-01014 分钟前
McpAgentExecutor 混合挂载:HTTP 工具与 NPX 服务器同时接入同一 Agent
java·agent·function call·spring ai·mcp·toolcall·java ai
XiYang-DING22 分钟前
【Java】反射
java·开发语言
ACGkaka_22 分钟前
JDK 版本管理工具介绍:jenv与sdkman(Mac端)
java·macos·sdkman
阿坤带你走近大数据24 分钟前
数据API接口的数据源和目标源分别是什么?怎么设置?
java·python·api
若阳安好27 分钟前
【java】任务流批处理平台
java·开发语言
艾莉丝努力练剑41 分钟前
【Linux线程】Linux系统多线程(六):<线程同步与互斥>线程同步(上)
java·linux·运维·服务器·c++·学习·线程
好家伙VCC41 分钟前
# BERT在中文文本分类中的实战优化:从基础模型到高效部署BERT(Bi
java·人工智能·python·分类·bert