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

深入理解 synchronized:到底锁的是谁?

在 Java 多线程并发编程里,synchronized是保证线程安全的核心关键字,但很多开发者只知道它能加锁,却不清楚它到底锁的是什么不同写法锁的范围有何区别

这篇文章就把 synchronized 的锁对象、作用范围、经典测试用例一次性讲透,代码与测试结果完全还原,帮你彻底搞懂 synchronized 的 “锁事”。


一、synchronized 锁的核心结论

synchronized 本质锁的是对象,而非代码!不同写法对应不同锁对象:

  1. 修饰实例方法→ 锁当前实例对象(this)
  2. 修饰静态方法→ 锁当前类的 Class 对象
  3. 修饰代码块→ 锁括号内指定的对象

只有锁的是同一个对象,多线程才会互斥等待;锁不同对象,互不影响。


二、完整测试用例(一模一样还原)

测试用例 1:synchronized 修饰实例方法(锁 this)

代码

public class SyncInstanceMethod { // 同步实例方法:锁当前对象 this public synchronized void test() { System.out.println(Thread.currentThread().getName() + " 进入同步方法"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 退出同步方法"); } public static void main(String[] args) { // 同一个对象 SyncInstanceMethod instance = new SyncInstanceMethod(); new Thread(() -> instance.test(), "线程A").start(); new Thread(() -> instance.test(), "线程B").start(); } }

执行结果

线程A 进入同步方法 线程A 退出同步方法 线程B 进入同步方法 线程B 退出同步方法

结论

同一个实例对象的同步方法,多线程互斥执行,锁是当前实例 this。


测试用例 2:不同实例调用实例同步方法(互不锁)

代码

public class SyncInstanceMethodDiff { public synchronized void test() { System.out.println(Thread.currentThread().getName() + " 进入同步方法"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 退出同步方法"); } public static void main(String[] args) { // 两个不同实例 SyncInstanceMethodDiff instance1 = new SyncInstanceMethodDiff(); SyncInstanceMethodDiff instance2 = new SyncInstanceMethodDiff(); new Thread(() -> instance1.test(), "线程A").start(); new Thread(() -> instance2.test(), "线程B").start(); } }

执行结果

线程A 进入同步方法 线程B 进入同步方法 线程A 退出同步方法 线程B 退出同步方法

结论

不同实例的同步方法,锁对象不同,不互斥,并发执行


测试用例 3:synchronized 修饰静态方法(锁 Class 对象)

代码

public class SyncStaticMethod { // 同步静态方法:锁当前类 Class 对象 public static synchronized void test() { System.out.println(Thread.currentThread().getName() + " 进入静态同步方法"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 退出静态同步方法"); } public static void main(String[] args) { new Thread(() -> SyncStaticMethod.test(), "线程A").start(); new Thread(() -> SyncStaticMethod.test(), "线程B").start(); } }

执行结果

线程A 进入静态同步方法 线程A 退出静态同步方法 线程B 进入静态同步方法 线程B 退出静态同步方法

结论

静态同步方法锁的是类的 Class 对象,全局唯一,所有线程互斥。


测试用例 4:synchronized 修饰代码块(指定锁对象)

代码

public class SyncBlock { // 自定义锁对象 private final Object lock = new Object(); public void test() { // 同步代码块:锁 lock 对象 synchronized (lock) { System.out.println(Thread.currentThread().getName() + " 进入同步代码块"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 退出同步代码块"); } } public static void main(String[] args) { SyncBlock instance = new SyncBlock(); new Thread(() -> instance.test(), "线程A").start(); new Thread(() -> instance.test(), "线程B").start(); } }

执行结果

线程A 进入同步代码块 线程A 退出同步代码块 线程B 进入同步代码块 线程B 退出同步代码块

结论

同步代码块锁指定对象,粒度更灵活,是企业开发推荐写法。


测试用例 5:实例锁 VS 类锁(互不干扰)

代码

public class SyncInstanceAndClass { // 实例方法锁:this public synchronized void instanceMethod() { System.out.println(Thread.currentThread().getName() + " 进入实例方法"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 退出实例方法"); } // 静态方法锁:Class public static synchronized void staticMethod() { System.out.println(Thread.currentThread().getName() + " 进入静态方法"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 退出静态方法"); } public static void main(String[] args) { SyncInstanceAndClass instance = new SyncInstanceAndClass(); new Thread(() -> instance.instanceMethod(), "线程A").start(); new Thread(() -> SyncInstanceAndClass.staticMethod(), "线程B").start(); } }

执行结果

线程A 进入实例方法 线程B 进入静态方法 线程A 退出实例方法 线程B 退出静态方法

结论

实例锁(this)和类锁(Class)是两把完全独立的锁,互不阻塞。


三、一张表总结 synchronized 锁对象

写法锁对象作用范围
实例方法 synchronized当前实例 this同一实例互斥
静态方法 synchronized当前类 Class全局所有实例互斥
同步代码块 synchronized (obj)指定对象 obj仅锁 obj 范围

四、核心要点回顾

  1. synchronized 永远锁对象,不锁代码。
  2. 只有锁同一个对象,才会互斥。
  3. 实例锁和类锁是两把独立锁,互不影响。
  4. 代码块锁粒度最细,性能最优,优先使用。

搞懂 synchronized 到底锁谁,是写出高并发、线程安全代码的第一步!

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

相关文章:

  • 2026冲刺用!全场景通用降AIGC平台 千笔·专业降AIGC智能体 VS 灵感ai
  • 【WebRTC】Webrtc-streamer实战:从RTSP到WebRTC的低延迟流媒体转发
  • IGMP V2
  • 随笔3
  • COMSOL锂枝晶应力模型:到手即用
  • 移远EC20模组TCP/IP通信实战:从AT指令到数据透传的完整流程(附常见错误排查)
  • 深度解析EEGNet中的可分离卷积:原理剖析与PyTorch实现技巧
  • 实测对比后 8个降AI率平台:毕业论文全流程必备测评与推荐
  • JavaWeb ——HttpServletRequest 请求对象(附代码)
  • OpenCloudOS 8实战:从零构建高性能WordPress企业官网
  • 高效SRT字幕转Word解决方案:一键批量处理doc与docx格式
  • Excel二维查表插值计算:从INCA到Excel的完整迁移指南(附工具下载)
  • 看完就会:全学科适配的降AI率网站 千笔·降AI率助手 VS Checkjie
  • DDR5内存排错指南:利用EpRC计数器定位故障内存条的物理位置
  • 这份榜单够用!10个降AIGC软件测评:开源免费必看,帮你高效降AI率
  • JavaWeb —— 过滤器 (Filter) 与监听器 (Listener) 全解析(附代码)
  • 别再只用pretrained=True了!timm库加载模型权重的5种实战姿势(附避坑清单)
  • 深入解析UDS(ISO14229) 0x34服务:RequestDownload的数据传输机制与工程实践
  • 3DSlicer实战:从零开始完成冠脉精准分割
  • 告别低效繁琐!普遍认可的降AI率平台 —— 千笔·专业降AIGC智能体
  • 单相并网逆变器MATLAB仿真:离网仿真与PLL锁相环下的电感电流谐波含量THD分析
  • 手把手教你用金蝶云苍穹插件搞定单据列表与动态表单的交互难题
  • PIM Sparse 模式
  • 论文省心了!10个降AIGC工具测评:开源免费,轻松降AI率过关
  • BLDC直流无刷电机FOC控制:Matlab/Simulink中的磁场定向控制实现
  • 豆包上怎么出现自己的公司?2026企业AI获客实操手册 - 品牌2026
  • WordPress中销售倒计时html小部件
  • 【手把手教程】阿里云OpenClaw一键部署指南,两步解锁龙虾AI助理!
  • 【节点】[SampleTexture3D节点]原理解析与实际应用
  • React15 - Redux-Persit 中 asyncSessionStorage 在web浏览器中存在吗?