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

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 机制和锁升级策略,在保证线程安全的同时,兼顾了性能。理解其底层原理有助于编写更高效、更安全的并发程序。

http://www.jsqmd.com/news/200141/

相关文章:

  • 2026年1月杭州品牌策划公司实力榜:全行业适配型、B2B品牌策划、城市文旅品牌策划、电动车品牌策划、杭州品牌设计、垂直领域深耕型五家机构凭专业与口碑出圈 - 海棠依旧大
  • 调试Dify插件总失败?你可能忽略了这4个关键细节
  • 还在为Dify描述长度受限发愁?这5个技巧让你轻松输出长文本
  • 完整教程:RabbitMQ_1_RabbitMQ概述
  • LIS
  • 品牌全案策划公司十大排行榜 (2025权威解析) - 品牌排行榜
  • CSDN官网技术博主都在用GLM-4.6V-Flash-WEB生成图文摘要
  • 【紧急避坑指南】:Dify多模态集成中不可忽视的7类数据格式错误
  • 深耕九年,铸就湾区活动策划标杆 —— 广州大江文化传媒有限公司实力解读 - torzi_JavaScript
  • Dify调试工具深度剖析,揭开插件性能瓶颈背后的秘密
  • HuggingFace镜像网站支持GLM-4.6V-Flash-WEB模型评分系统
  • HTML中使用Flex布局实现双行夹批效果
  • 耐力板厂家品牌测评:ISO三体系认证 + 自主研发能力(品牌对比) - 品牌排行榜
  • 迁移CSDN到hexo
  • MyBatisPlus逻辑删除应用于GLM-4.6V-Flash-WEB历史数据管理
  • ARM栈展开原理解析
  • 2026年火锅底料供应链推荐:火锅底料工厂与火锅底料厂家深度解析 - 速递信息
  • 年终奖10w的同事,写的代码那叫一个优雅!
  • 输入宠物品种和习性,用可拓互动思维,输出训练+玩耍的宠物互动方案,增进感情。
  • Git Commit模板配置提升GLM-4.6V-Flash-WEB协作效率
  • 深入探索增量型PID控制器的多种优化算法
  • 微PE官网工具链升级:GLM-4.6V-Flash-WEB识别RAID配置界面
  • 一种奇特的干掉 if..else 方式,Spring Boot+Aviator+Aop 挺有趣!
  • gui自动化—2.键盘控制
  • HuggingFace镜像网站同步上线GLM-4.6V-Flash-WEB,下载更高效
  • CSDN官网热榜文章是如何用GLM-4.6V-Flash-WEB生成的?
  • OpenTeleDB:在千万级“秒杀”模拟中,它真的治好了我的 PostgreSQL Vacuum 焦虑吗?
  • Git Commit签署密钥保护GLM-4.6V-Flash-WEB代码完整性
  • 【Dify权限系统构建指南】:彻底搞懂access_token配置原理与实战
  • Dify access_token配置终极手册(附生产环境配置模板)