对象锁 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 并发编程中锁机制的关键一步。

相关推荐
代码什么用13 分钟前
Spring基础使用
java·后端·spring
Su米苏36 分钟前
Spring AI 中MCP 与普通 @Tool的区别
java·人工智能·spring
明月_清风41 分钟前
Deno 终局来了:从挑战 Node 到被 Cloudflare 收编
前端·后端·node.js
码云数智-园园1 小时前
unique_ptr 还是 shared_ptr?C++ 智能指针选型与内存泄漏实战分析
java·开发语言
老板一杯拿铁1 小时前
Java 异常体系详解:从字节码原理到最佳实践
java
蜗牛互联网1 小时前
Java 17 HttpClient调用文件转写API的超时与失败回退
java·人工智能·后端
禾小西2 小时前
07丨Redis 哨兵机制:主库故障后,如何恢复服务?
java·开发语言·redis
我不是阵雨2 小时前
JDK 21虚拟线程Pinning陷阱:一文拔钉解困
java·开发语言
小卡车5552 小时前
java反射、自定义注解的应用(自定义分页)
java
BLUcoding3 小时前
接口服务公网超时排查记录:SecureRandom 阻塞问题分析与解决
java·linux·springboot·aes·securerandom