
synchronized 实例方法的互斥性取决于调用该方法的对象实例——不同实例的同一同步方法可被多个线程同时执行;只有当多个线程操作同一个对象实例时,才会因共享同一 this 锁而相互阻塞。
`synchronized` 实例方法的互斥性取决于调用该方法的对象实例——不同实例的同一同步方法可被多个线程**同时执行**;只有当多个线程操作**同一个对象实例**时,才会因共享同一 `this` 锁而相互阻塞。
在 Java 并发编程中,synchronized 关键字的作用本质是基于对象监视器(monitor) 的加锁机制。对于实例方法,synchronized 修饰符等价于在方法体外包裹一个 synchronized(this) 块——即以当前对象实例(this)作为锁对象。这意味着:锁的粒度是对象级别,而非方法或类级别。
因此,是否发生线程阻塞,关键不在于“是不是同一个方法”,而在于“是不是同一个 this 对象”。
✅ 正确理解:锁对象决定并发行为
以下代码清晰展示了这一机制:
public class SynchronizedExchanger {
private Object object = null;
public synchronized void setObject(Object o) {
System.out.println(Thread.currentThread().getName() +
" entering setObject: " + o);
try {
Thread.sleep(10); // 模拟耗时操作,便于观察并发
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
this.object = o;
System.out.println(Thread.currentThread().getName() +
" exiting setObject: " + o);
}
}
// 测试:两个独立实例 → 无竞争,可并行执行
public class SynchronizedExchangerMainDemo {
public static void main(String[] args) {
SynchronizedExchanger ex1 = new SynchronizedExchanger();
SynchronizedExchanger ex2 = new SynchronizedExchanger();
Thread t1 = new Thread(() -> {
for (int i = 0; i {
for (int i = 0; i <p>运行结果中,<code>Thread-1</code> 和 <code>Thread-2</code> 的日志会明显<strong>交错输出</strong>(如 <code>Thread-1 entering...</code>、<code>Thread-2 entering...</code> 几乎同时出现),证明二者未相互等待——因为 <code>ex1</code> 和 <code>ex2</code> 是两个不同的对象,各自持有独立的 monitor 锁。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8775" title="Java Maven Common"><img
src="https://img.php.cn/upload/skill/000/000/081/179222954019613.jpg" alt="Java Maven Common" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill8775" title="Java Maven Common" class="overflowclass">Java Maven Common</a>
<p class="overflowclass">Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。</p>
</div>
<a rel="nofollow" href="/xiazai/skill8775" title="Java Maven Common" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div><h3>❌ 常见误区澄清</h3>
- ❌ “
synchronized方法 = 全局串行” → 错。它只对同一锁对象上的同步块/方法生效。 - ❌ “所有
setObject()调用都互斥” → 错。只有调用发生在同一实例上时才互斥。 - ✅ 正确理解:
synchronized实例方法 ≡synchronized(this) { ... },锁的是this引用所指向的具体对象。
? 进阶提示:如何实现跨实例互斥?
若需让多个对象实例共用一把锁(例如全局计数器、单例资源访问),应显式指定同一个锁对象,例如:
public class GlobalLockExchanger {
private static final Object GLOBAL_LOCK = new Object(); // 静态共享锁
private Object object = null;
public void setObject(Object o) {
synchronized (GLOBAL_LOCK) { // 所有实例共用此锁
System.out.println(Thread.currentThread().getName() + " locked globally");
this.object = o;
}
}
}
此时,无论多少个 GlobalLockExchanger 实例,只要调用 setObject(),都会竞争 GLOBAL_LOCK,从而实现跨实例同步。
✅ 总结
-
synchronized实例方法的锁对象是this,即调用该方法的具体对象实例; - 不同实例 → 不同锁 → 可并发执行;
- 相同实例 → 同一锁 → 互斥执行;
- 理解锁对象(monitor)的本质,是掌握 Java 同步机制的核心前提;
- 避免想当然地认为“同步方法=绝对串行”,务必结合锁对象的生命周期与可见性分析。
掌握这一点,你就能准确预判多线程场景下的执行顺序,并合理设计锁粒度——既保障线程安全,又避免过度同步导致性能瓶颈。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










