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

相关推荐
妙码生花11 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十七):登录接口完善,登录页接口整合,解决跨域
前端·后端·ai编程
SamDeepThinking11 小时前
从源码到代码:MyBatis-Flex 与 MyBatis-Plus 的逐项对比
java·后端·程序员
shepherd11111 小时前
一文带你掌握 LLM、Token、Context、Prompt、RAG、MCP、Skill、Agent 等 AI 核心概念
人工智能·后端·ai编程
狂炫冰美式12 小时前
人均配了AI, 为什么公司还是没变快? 🤔 本质还是分布式系统问题
前端·后端·架构
她的男孩14 小时前
Spring Boot 接 Flowable 工作流:用 3 个注解搭一个请假审批流程
java·后端·架构
爱读源码的大都督14 小时前
Claude Code源码分析(三):为什么系统提示词中需要有tools呢?
前端·人工智能·后端
爱勇宝14 小时前
Claude Code 被曝暗藏“隐形检测”代码:封代理不是最可怕的,可怕的是你根本不知道它在干什么
前端·后端·程序员
ITOM运维行者14 小时前
从零搭建企业级服务器监控体系:踩坑实录与架构设计
前端·后端
用户40993225021215 小时前
Vue状态管理入门第四章:组合式store和SSR风险
前端·vue.js·后端
用户342323237631715 小时前
SPI 通信与高速外设驱动详解
后端