对象锁本质是锁住当前实例对象本身,单实例时多线程串行执行、效果近似类锁,多实例时各锁独立互不干扰;选择依据是业务语义:保护实例状态用对象锁,保护全局资源必须用类锁或分布式锁。

Java 中对象锁(synchronized 实例方法或 synchronized(this))的本质,是锁住“当前对象实例”本身。所以它的行为完全取决于你用的是单个实例,还是多个实例——不是语法不同,而是锁的粒度和作用范围发生了根本变化。
单实例下:对象锁 ≈ 类锁效果
当整个应用只存在一个该类的对象(比如 Spring 默认的 singleton scope、手写饿汉/双重检查单例),那么所有线程调用它的 synchronized 实例方法时,实际都在竞争同一把锁(即那个唯一对象的 monitor)。此时:
- 多个线程对同一个实例的多个 synchronized 方法调用,会串行执行
- 即使方法签名不同、逻辑无关,只要属于该实例,就互斥
- 效果上接近 static synchronized(类锁),但底层锁对象不同:一个是实例对象,一个是
MyClass.class
多实例下:对象锁彼此完全独立
每次 new 一个新对象,JVM 就为其分配独立的监视器(monitor)。哪怕类型相同、代码一致,锁也互不感知:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
new Service().deductStock()和new Service().deductStock()可同时执行 - 常见于 Spring prototype bean、Web 中每次请求 new 的 Action、测试中随手 new 的对象
- 若业务本意是“全局扣库存”,却误用多实例 + 实例锁,就会出现超卖——这就是知识库强调的“致命死穴”
怎么判断你面对的是单例还是多例?
不能只看类有没有写单例模式,而要看运行时真正被使用的对象是不是同一个:
立即学习“Java免费学习笔记(深入)”;
- Spring 环境下:查 Bean scope,默认是 singleton;prototype 则每次 getBean() 都新建
- 手动管理对象:看创建方式——是静态 getInstance() 返回同一个,还是到处 new
- 集群部署时:单机单例 ≠ 全局单例,跨 JVM 仍需分布式锁
该用哪种锁?关键看业务语义
锁不是越“重”越好,而是要匹配你的并发控制目标:
- 保护某个具体对象的状态(如用户 session 数据)→ 用对象锁(天然合适)
- 保护全局资源(如总库存、配置开关)→ 必须用类锁(
synchronized(MyClass.class))或更稳妥的static final Object LOCK = new Object() - 跨进程/集群场景 → 对象锁、类锁都失效,必须升级为 Redis 分布式锁、ZooKeeper 临时节点等

















