对象锁 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();
    }
}

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

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

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

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

相关推荐
计算机学姐几秒前
基于SpringBoot的健身房管理系统【智能推荐算法+可视化统计】
java·vue.js·spring boot·后端·mysql·spring·推荐算法
海边捡石子7 分钟前
java内存泄漏问题排查和JVM调优
java·后端
申阳15 分钟前
Day 10:08. 基于Nuxt开发博客项目-关于我页面开发
前端·后端·程序员
yunyi21 分钟前
使用go的elastic库来实现前后端模糊搜索功能
前端·后端
考虑考虑25 分钟前
JDK25中的super
java·后端·java ee
一 乐36 分钟前
个人健康系统|健康管理|基于java+Android+微信小程序的个人健康系统设计与实现(源码+数据库+文档)
android·java·数据库·vue.js·spring boot·生活
bagadesu1 小时前
28.<Spring博客系统⑤(部署的整个过程
java·后端
百锦再1 小时前
第14章 智能指针
android·java·开发语言·git·rust·go·错误
zhong liu bin1 小时前
Java并发编程【JUC】【一】
java·开发语言·juc
老华带你飞1 小时前
医疗保健|医疗养老|基于Java+vue的医疗保健系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·医疗保健