news 2026/9/2 14:04:22

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/9/3 1:13:58

Linux怎么查找某个文件?

在Linux系统管理与开发操作中&#xff0c;快速定位文件是高频刚需&#xff0c;不管是查找配置文件、日志文件还是脚本文件&#xff0c;选对查找命令都能节省大量时间。那么Linux怎么查找某个文件?请看下文。find&#xff1a;实时、精准、功能强适合需要最新结果、按权限/大小/…

作者头像 李华
网站建设 2026/9/2 23:25:11

基于微信小程序的社区便利店购物平台系统(毕设源码+文档)

课题说明 随着社区经济与即时零售的快速发展&#xff0c;居民对便捷购物的需求日益凸显&#xff0c;但传统社区便利店存在线上服务缺失、商品展示有限、配送响应滞后、会员管理零散等问题&#xff0c;难以适配居民“足不出户、即时送达”的消费需求&#xff0c;也制约了便利店的…

作者头像 李华
网站建设 2026/9/2 21:48:15

你还在手动处理多模态数据?Dify自动化格式引擎已悄然升级!

第一章&#xff1a;Dify多模态数据格式的演进与意义Dify 作为面向 AI 原生应用开发的低代码平台&#xff0c;其对多模态数据的支持能力在不断演进中逐步深化。随着文本、图像、音频和视频等复合类型数据在实际业务场景中的广泛应用&#xff0c;Dify 的数据格式设计也从单一文本…

作者头像 李华
网站建设 2026/9/2 21:53:43

为什么90%的开发者都用不好Dify调试工具?真相令人震惊

第一章&#xff1a;Dify插件调试工具的核心价值Dify插件调试工具为开发者提供了一套高效、直观的本地开发与测试环境&#xff0c;显著降低了AI应用集成过程中的调试复杂度。通过实时日志输出、请求模拟和上下文追踪功能&#xff0c;开发者能够在不依赖生产环境的情况下完成插件…

作者头像 李华
网站建设 2026/9/2 21:51:41

FastStone Capture注册码太贵?免费使用GLM-4.6V-Flash-WEB截图分析

FastStone Capture注册码太贵&#xff1f;用GLM-4.6V-Flash-WEB实现免费智能截图分析 你有没有遇到过这种情况&#xff1a;为了排查一个简单的界面问题&#xff0c;客户甩来一张模糊的截图&#xff0c;上面满是弹窗、按钮和报错信息&#xff0c;而你只能逐个放大像素去辨认&am…

作者头像 李华
网站建设 2026/9/2 21:57:41

为什么90%的AI项目败在数据格式?Dify多模态实践给出答案

第一章&#xff1a;为什么90%的AI项目败在数据格式&#xff1f;在人工智能项目的实施过程中&#xff0c;数据被视为燃料&#xff0c;而数据格式则是输送燃料的管道。即便模型架构再先进&#xff0c;若输入数据格式不统一、结构混乱或存在语义歧义&#xff0c;模型训练将难以收敛…

作者头像 李华