对象锁 vs 类锁:Java 并发中的隐形对决

摘要

在 Java 并发编程中,synchronized 既可以作用于对象实例(对象锁),也可以作用于类对象(类锁)。很多开发者容易混淆二者,导致锁使用不当。本文深入解析对象锁与类锁的区别、适用场景,并结合代码示例帮助你彻底搞懂。


正文

一、对象锁与类锁的概念

  1. 对象锁(Instance Lock)
  • 通过 synchronized 修饰 实例方法 或 对象实例代码块。
  • 锁定的粒度:当前对象实例(this) 。
  • 多个对象实例之间互不影响。
java 复制代码
public synchronized void instanceMethod() {
    // 对象锁,锁住 this
}
  1. 类锁(Class Lock)
  • 通过 synchronized 修饰 静态方法 或 类对象代码块。
  • 锁定的粒度:Class 对象(Class<?> clazz) 。
  • 整个类范围内共享同一把锁。
java 复制代码
public static synchronized void staticMethod() {
    // 类锁,锁住 MyClass.class
}

二、对象锁 vs 类锁的区别

对比维度 对象锁 类锁
锁定范围 单个实例 整个类
锁对象 this(实例) Class 对象
并发影响 多个实例可并行 整个类只能一个线程进入
使用场景 保护实例字段 保护静态字段或全局资源
是否互斥 不与类锁互斥 不与对象锁互斥

三、代码示例

1. 对象锁互斥(不同线程访问同一实例)
java 复制代码
public class Demo {
    public synchronized void instanceMethod() {
        System.out.println(Thread.currentThread().getName() + " 进入对象锁方法");
        try { Thread.sleep(2000); } catch (InterruptedException e) {}
        System.out.println(Thread.currentThread().getName() + " 退出对象锁方法");
    }
    
    public static void main(String[] args) {
        Demo demo = new Demo();
        new Thread(demo::instanceMethod, "T1").start();
        new Thread(demo::instanceMethod, "T2").start();
    }
}

结果:T1 与 T2 串行执行,因为它们竞争的是同一个对象锁。

2. 多个对象实例(对象锁不互斥)
java 复制代码
Demo d1 = new Demo();
Demo d2 = new Demo();
new Thread(d1::instanceMethod, "T1").start();
new Thread(d2::instanceMethod, "T2").start();

结果:T1 和 T2 并发执行,因为它们持有不同对象的锁。

3. 类锁互斥(静态方法)
java 复制代码
public static synchronized void staticMethod() {
    System.out.println(Thread.currentThread().getName() + " 进入类锁方法");
    try { Thread.sleep(2000); } catch (InterruptedException e) {}
    System.out.println(Thread.currentThread().getName() + " 退出类锁方法");
}

即使是不同实例,调用该方法也会被互斥,因为锁住的是 Demo.class。


四、常见误区

  1. 以为对象锁和类锁会互斥
  • 错误认识:对象锁和类锁会阻塞对方。
  • 实际情况:它们互不干扰,一个线程拿对象锁,另一个线程拿类锁,能同时执行。
  1. 错误选择锁粒度
  • 锁住 this 时要确保锁对象唯一,否则会失效。
  • 静态变量竞争必须用类锁,否则无法保证一致性。

五、适用场景

  1. 对象锁
  • 用于保护 实例变量;
  • 适合在 多用户多对象 场景(如:每个用户购物车互不干扰)。
  1. 类锁
  • 用于保护 静态变量/全局资源;
  • 适合在 跨实例共享资源 场景(如:订单号生成器、配置缓存)。

六、总结

  • 对象锁:锁住的是单个实例,适用于保护实例级资源。
  • 类锁:锁住的是类对象,适用于保护类级资源。
  • 二者不互斥:对象锁和类锁独立存在,不能相互替代。
  • 最佳实践:根据资源粒度选择合适的锁,避免锁范围过大造成性能瓶颈。

理解对象锁 vs 类锁,是掌握 Java 并发编程中锁机制的关键一步。

相关推荐
Tokenfree13 小时前
给大模型调用加一个熔断器:60 行代码,三个阈值
后端
Jason_chen13 小时前
Linux 进程调度器深入解析与实时性优化指南(基于 Linux 5.10+)
后端
1360967572313 小时前
三个 Agent 干同一个活,职责边界到底该怎么划
后端
小嘉丶学长13 小时前
Day14 · 字典与集合
java·开发语言·网络·python·学习·1024程序员节
房西杭13 小时前
GM 指令:修改玩家属性
后端
字节探索13 小时前
Spring Boot 接口幂等性设计:从唯一索引到 Redis+Lua 的工程实践
java·spring boot
用户37215742613513 小时前
Java 实现 Excel 与 Markdown 相互转换:表格导出、格式设置与多表提取
java
胡写代码13 小时前
删掉的数据还占着唯一键:逻辑删除 + 唯一索引的四次取舍
spring boot·后端
IT_陈寒13 小时前
React的useEffect依赖数组把我坑惨了
前端·人工智能·后端
用户83562907805114 小时前
Python 调整 Excel 工作表显示设置
后端·python