颠覆认知!synchronized 的轻量级锁竟然还会自旋?

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

颠覆认知!synchronized 的轻量级锁竟然还会自旋?

前些天,项目组里刮起一阵"性能优化"旋风。大家嘴里念叨得最多的,就是 synchronized。你以为 synchronized 还停留在"重量级锁开销大、能不用别用"的时代?哎,too young, too simple。有同事突然冒出一句:"你知道轻量级锁会自旋么?" 我心里那个一惊,啥玩意?自旋我知道,但不是只有自旋锁(spin lock)和偏向锁那一套撩妹操作么?轻量级锁还能自旋?我的认知小船翻了。


说起来,本来我一直用了十几年的 synchronized,早就当它透明胶带:粘一粘,线程安全就稳了。直到看热心网友贴出来的 JVM 官方文档,才发现原来 synchronized 内部也有个熬夜加班的"小老弟"------自旋。

synchronized 锁升级流程:

  • 偏向锁
  • 轻量级锁(可能自旋)
  • 重量级锁(OS 层阻塞)

你没看错,真·自旋,出现在了轻量级锁阶段!


探索过程:锁的"瘦身房"与自旋岗

那天熬夜调代码,忍不住扒拉出 jvisualvm 跟踪锁的情况。说实话,一开始我还以为自旋只跟 ReentrantLock 那种高阶锁精英挂钩,synchronized 这种老实人不会玩这一套。谁知道 JVM 1.6 以后,synchronized 静悄悄地玩起了锁升级+自旋优化!

简单来说,轻量级锁抢不到怎么办?慌什么!线程先自旋个几次------有机会就抢过来,没机会再罢休。换句话说,JVM 在"阻塞"之前还会帮你"抢红包"兜底几下,说不定你卡个 1ms 就能等到 CPU 空。

我随手写了个脑筋急转弯式的多线程代码测试([完整示例略]),线程争锁的时候明显能感觉比老版 JVM 更"丝滑"。

只看关键代码逻辑:

java 复制代码
synchronized (lock) {
    // 临界区代码
    doSthImportant();
}
// JVM 内部:如果锁已轻量级化,CAS 尝试获取锁
// 若失败,线程本地自旋次数,等锁释放再抢

你看,JVM 真不是简单粗暴地让你傻等。


踩坑瞬间

当然,自旋背后也有坑货时刻。举个例子:

  • 多线程并发极高时,轻量级锁依然会撑不住,很快升级成"重量级锁",从会场 VIP 区秒变大排长队,性能立马暴跌。
  • 自旋也是"徒劳等待"------万一锁持有者忙着GC或I/O,兄弟你再怎么转也只是在原地打转,CPU 就这么白白烧光。

我有次手贱把 synchronized 放到了很大的代码块上,结果 CPU 飙升,线程堆积,"自旋"变成了"原地画圆"(线程:我到底在等什么?)。真是又气又好笑。


经验启示

码代码久了,归纳如下几点生存小妙招:

  • synchronized 其实很聪明,JVM 已帮你做了不少"骚操作",不用过分妖魔化它。
  • 遇到频繁竞争,锁粒度要细,临界区能短则短,别让自旋线程干等太久。
  • 想极致性能且偏好 DIY,可以考虑显式用 java.util.concurrent 包里的锁,但别轻视 synchronized 的进化史。
  • 工具很重要,有事多用 jstack、jvisualvm 等实时监控,别拍脑袋猜测锁状态。

最后,synchronized's not dead。别小瞧了轻量级锁下那颗自旋的心。从此,每次写 synchronized,总感觉背后有个 JVM 小哥在我耳边说:"兄dei,放心,让我帮你兜一把!"


好啦,今天先聊到这,码字都快饿了。谁能想到 synchronized 背后藏了那么多脑洞呢?下回也许还得扒拉扒拉偏向锁的故事......下期再见👋。

相关推荐
我命由我123454 分钟前
Android WebView - loadUrl 方法的长度限制
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
前端架构师-老李11 分钟前
Maven安装以及环境变量配置(macOS)
java·macos·maven
带刺的坐椅34 分钟前
(对标 Spring IA 和 LangChain4j)Solon AI & MCP v3.7.0, v3.6.4, v3.5.8 发布(支持 LTS)
java·spring·ai·solon·mcp·langchain4j
7澄136 分钟前
深入解析 LeetCode 1572:矩阵对角线元素的和 —— 从问题本质到高效实现
java·算法·leetcode·矩阵·intellij-idea
诗9趁年华40 分钟前
缓存三大问题深度解析:穿透、击穿与雪崩
java·spring·缓存
阳光明媚sunny41 分钟前
分糖果算法题
java·算法
whltaoin41 分钟前
【JAVA全栈项目】弧图图-智能图床SpringBoot+MySQL API接口结合Redis+Caffeine多级缓存实践解析
java·redis·spring·缓存·caffeine·多级缓存
一 乐1 小时前
医疗管理|医院医疗管理系统|基于springboot+vue医疗管理系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·医疗管理系统
华仔啊1 小时前
SpringBoot 2.x 和 3.x 的核心区别,这些变化你必须知道
java·spring boot·后端
laocooon5238578861 小时前
大数的阶乘 C语言
java·数据结构·算法