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

时间:2025-09-07 14:30:02来源:互联网

下面小编就为大家分享一篇对象锁 vs 类锁:Java 并发中的隐形对决,具有很好的参考价值,希望对大家有所帮助。

摘要

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


正文

一、对象锁与类锁的概念

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

二、对象锁 vs 类锁的区别

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

三、代码示例

1. 对象锁互斥(不同线程访问同一实例)
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. 多个对象实例(对象锁不互斥)
Demo d1 = new Demo();
Demo d2 = new Demo();
new Thread(d1::instanceMethod, "T1").start();
new Thread(d2::instanceMethod, "T2").start();

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

3. 类锁互斥(静态方法)
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 并发编程中锁机制的关键一步。

本站部分内容转载自互联网,如果有网站内容侵犯了您的权益,可直接联系我们删除,感谢支持!