You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用static对象作为synchronized锁,多线程调用同实例方法为何两次打印Before a

核心原因

你观察到的现象是Object.wait()方法的固有机制导致的,和synchronized本身的互斥性没有冲突:线程在同步块内调用锁对象的wait()方法时,会主动释放当前持有的锁,进入该锁对象的等待队列阻塞,这个设计是为了让其他线程可以拿到锁,触发notify/notifyAll操作,否则等待的线程永远没有被唤醒的机会,直接形成死锁。

synchronized的互斥性始终生效,同一时间永远只有一个线程持有锁执行同步块内的代码,两次打印Before a是第一个线程释放锁之后,第二个线程才拿到锁进入同步块执行的,并不是两个线程同时进入同步块。


执行流程完整拆解

你提供的代码执行顺序如下:

package com.data;

class TestThread {
    private final static Object object = new Object();

    public void myWaitMethod() {
        synchronized (object) {
            System.out.println("Before a " + Thread.currentThread().getId());
            try {
                object.wait();
            } catch (Exception ignore) {
                System.out.println(Thread.currentThread().getId());
            }
            System.out.println("After a " + Thread.currentThread().getId());
        }
    }

    public void myNotifyMethod() {
        synchronized (object) {
            System.out.println("Before Notify");
            object.notifyAll();
            System.out.println("After b");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestThread aa1 = new TestThread();
        new Thread(() -> aa1.myWaitMethod()).start();
        new Thread(() -> aa1.myWaitMethod()).start();
        Thread.sleep(1000);
        System.out.println("sleep");
        Thread.sleep(1000);
        aa1.myNotifyMethod();
    }
}
  1. 第一个启动的子线程(ID=12)率先抢到object锁,进入同步块,打印Before a 12,之后调用object.wait(),主动释放object锁,进入object的等待队列阻塞。
  2. 第二个子线程(ID=13)此时可以拿到刚被释放的object锁,进入同步块,打印Before a 13,同样调用object.wait(),释放锁后进入等待队列阻塞。
  3. main线程休眠2秒后调用myNotifyMethod(),抢到object锁,打印Before Notify,调用notifyAll()唤醒所有在object等待队列的线程,执行完同步块后释放锁。
  4. 被唤醒的两个子线程需要重新争抢object锁,抢到锁的线程继续执行wait()之后的逻辑,打印After a后释放锁,另一个线程抢到锁后再执行剩余逻辑,就得到了你看到的输出结果。

补充注意点

被notify/notifyAll唤醒的线程并不会直接继续执行,必须重新抢到对应的锁之后,才会从wait()调用的位置继续往下执行。

内容的提问来源于stack exchange,提问作者azzu112

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 21:27:03