news 2026/7/27 8:53:31

Synchronized 原理详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Synchronized 原理详解

一、synchronized 的基本概念

1.1 作用

synchronized是 Java 中的关键字,用于实现线程同步,确保:

  • 原子性:确保多个操作要么全部执行,要么全部不执行

  • 可见性:确保一个线程修改共享变量后,其他线程能立即看到

  • 有序性:防止指令重排序

1.2 使用方式

// 1. 同步实例方法 public synchronized void instanceMethod() { // 锁是当前实例对象 } // 2. 同步静态方法 public static synchronized void staticMethod() { // 锁是当前类的Class对象 } // 3. 同步代码块 public void method() { synchronized (lockObject) { // 锁是指定的对象 } }

二、底层实现原理

2.1 Java 对象头

每个 Java 对象在内存中都包含对象头,其中与锁相关的信息存储在 Mark Word 中:

32位 JVM 对象头布局:

|--------------------------------------------------------------| | Mark Word (32 bits) | |--------------------------------------------------------------| | 锁状态 | 25 bits | 4 bits | 1 bit | 2 bits | |-----------------|-------------------|--------|-------|--------| | 无锁 | hashCode | 分代年龄 | 0 | 01 | | 偏向锁 | ThreadID | Epoch | 分代年龄 | 1 | 01 | | 轻量级锁 | 指向栈中锁记录的指针 | | 00 | | 重量级锁 | 指向重量级锁(Monitor)的指针 | | 10 | | GC标记 | 空 | | | 11 |

64位 JVM 对象头布局类似,只是位数不同。

2.2 Monitor 机制

synchronized是通过 Monitor(监视器锁)实现的:

// 字节码层面 public void synchronizedMethod() { synchronized (this) { // 业务代码 } } // 对应的字节码: 0: aload_0 1: dup 2: astore_1 3: monitorenter // 进入同步块 4: aload_1 5: monitorexit // 正常退出 6: goto 14 9: astore_2 10: aload_1 11: monitorexit // 异常退出 12: aload_2 13: athrow 14: return

三、锁升级过程(锁膨胀)

Java 6 之后,synchronized 实现了锁升级机制,以提高性能:

3.1 无锁状态

初始状态,对象未被任何线程锁定。

3.2 偏向锁(Biased Locking)

适用场景:只有一个线程访问同步块

流程:

  1. 线程第一次访问同步块时,检查 Mark Word 中的锁标志位

  2. 如果是 01(无锁/偏向锁),通过 CAS 将线程 ID 写入 Mark Word

  3. 成功则获取偏向锁,锁标志位不变(仍是 01)

  4. 后续同一线程进入时,只需检查线程 ID 是否匹配

优点:只有一个线程时,性能接近无锁

3.3 轻量级锁(Lightweight Locking)

触发条件:有多个线程竞争,但竞争不激烈

流程:

  1. 当有第二个线程尝试获取锁时,偏向锁升级为轻量级锁

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

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

  4. 尝试通过 CAS 将对象头替换为指向锁记录的指针

  5. 成功则获得锁,失败则自旋重试

自旋策略:

  • 自旋次数有限(默认 10 次,可通过参数调整)

  • 自适应自旋:根据上次自旋成功与否动态调整

3.4 重量级锁(Heavyweight Locking)

触发条件:竞争激烈或自旋失败

流程:

  1. 轻量级锁升级为重量级锁

  2. 对象头指向操作系统层面的互斥量(Mutex)

  3. 未获取锁的线程进入等待队列,被操作系统挂起

  4. 需要用户态到内核态的切换,开销大

四、锁的优缺点对比

锁类型优点缺点适用场景
偏向锁加锁解锁无额外消耗有竞争时会额外消耗单线程访问
轻量级锁竞争线程不阻塞,自旋自旋消耗CPU追求响应时间,同步块执行快
重量级锁竞争线程不消耗CPU线程阻塞,响应慢追求吞吐量,同步块执行时间长

五、锁优化技术

5.1 锁消除(Lock Elimination)

public String concatString(String s1, String s2, String s3) { // StringBuffer 是线程安全的,但这里 sb 是局部变量 // JVM 检测到 sb 不可能逃逸出方法,会消除锁 StringBuffer sb = new StringBuffer(); sb.append(s1); sb.append(s2); sb.append(s3); return sb.toString(); }

5.2 锁粗化(Lock Coarsening)

// 多次加锁解锁合并为一次 for (int i = 0; i < 1000; i++) { synchronized (this) { // JVM 可能会合并这1000次锁操作 // do something } } // 可能优化为: synchronized (this) { for (int i = 0; i < 1000; i++) { // do something } }

5.3 自适应自旋(Adaptive Spinning)

JVM 根据之前的自旋成功率动态调整自旋次数。

六、与 ReentrantLock 对比

特性synchronizedReentrantLock
实现方式JVM 内置Java API 实现
锁获取自动获取释放手动 lock/unlock
可中断不支持支持
公平锁非公平可选公平/非公平
条件变量只能有一个可创建多个 Condition
性能Java 6 后优化,两者接近功能更丰富

七、使用建议

  1. 优先使用 synchronized:在 Java 6+ 中性能已大幅优化

  2. 减少锁粒度:使用细粒度锁,减少竞争

  3. 缩短持有时间:同步块内代码尽可能少

  4. 避免嵌套锁:防止死锁

  5. 考虑读写分离:读多写少场景使用 ReadWriteLock

八、常见问题

Q1: synchronized 能否重入?

可以。同一线程可重复获取同一把锁。

Q2: synchronized 是否公平?

默认非公平。但有一定偏向:进入等待队列前会尝试直接获取锁。

Q3: synchronized 能否中断?

不能。线程在等待锁时不能被中断。

Q4: synchronized 锁的是什么?

  • 实例方法:锁的是当前对象实例(this)

  • 静态方法:锁的是当前类的 Class 对象

  • 同步块:锁的是括号里的对象

总结

synchronized是 Java 并发编程的基石,通过对象头、Monitor 机制和锁升级策略,在保证线程安全的同时,兼顾了性能。理解其底层原理有助于编写更高效、更安全的并发程序。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/27 2:53:01

从单机搜索到分布式高可用搜索与实时索引体系落地的互联网系统工程实践随笔与多语言语法思考

在现代互联网系统中&#xff0c;搜索不仅是用户体验的核心&#xff0c;还承担数据分析、推荐和业务监控功能。然而&#xff0c;单机搜索在海量数据和高并发请求下容易出现查询延迟、阻塞或节点宕机。本文围绕分布式高可用搜索体系展开&#xff0c;结合多语言代码示例&#xff0…

作者头像 李华
网站建设 2026/7/27 2:52:59

ADB调试桥接GLM-4.6V-Flash-WEB Android设备上的视觉任务

ADB桥接GLM-4.6V-Flash-WEB在Android设备上的视觉任务实践 在移动AI应用快速演进的今天&#xff0c;越来越多开发者希望将前沿多模态大模型部署到真实终端设备上进行验证与迭代。然而&#xff0c;受限于边缘算力、调试工具链不完善以及模型体积庞大等问题&#xff0c;许多实验室…

作者头像 李华
网站建设 2026/7/27 2:52:57

HuggingFace镜像网站同步智谱AI最新模型GLM-4.6V-Flash-WEB

HuggingFace镜像网站同步智谱AI最新模型GLM-4.6V-Flash-WEB 在如今这个“图像即信息”的时代&#xff0c;用户每天上传数以亿计的图片——从电商商品页到社交媒体截图&#xff0c;从教育资料到医疗报告。可问题是&#xff0c;传统AI系统能“看见”这些图&#xff0c;却很难真正…

作者头像 李华
网站建设 2026/7/27 2:52:55

Docker Healthcheck指令监控GLM-4.6V-Flash-WEB服务状态

Docker Healthcheck 指控 GLM-4.6V-Flash-WEB 服务状态 在如今的 AI 应用部署中&#xff0c;一个常见的尴尬场景是&#xff1a;模型服务看似“运行正常”&#xff0c;进程没挂、端口也开着&#xff0c;但一旦发起请求&#xff0c;却迟迟无响应——这往往是因为显存泄漏、推理卡…

作者头像 李华
网站建设 2026/7/27 2:52:53

多模态数据落地难题全解析,Dify格式规范如何破局?

第一章&#xff1a;多模态数据落地难题全解析&#xff0c;Dify格式规范如何破局&#xff1f;在人工智能应用快速演进的当下&#xff0c;多模态数据&#xff08;文本、图像、音频、视频等&#xff09;的融合处理成为关键挑战。企业面临的核心问题不仅在于数据类型的多样性&#…

作者头像 李华
网站建设 2026/7/23 6:59:55

面试被问:OOM类型有哪些?怎么答?

面试官&#xff1a;OOM类型有哪些&#xff1f;你&#xff1a;就是老年代放不下了嘛&#xff01;面试官&#xff1a;等消息吧&#xff01;OOM&#xff08;Out Of Memory&#xff09; 错误有多种类型&#xff0c;每种类型对应不同的内存区域或触发场景。以下是常见的 OOM 类型及其…

作者头像 李华