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

能否不使用专用线程正确使用synchronized、wait()和notify()?

Java wait()/notify() 单线程调用挂起问题解析

我编写了一段使用synchronized块、wait()和notify()的Java代码:

public class mutex {
    
    private Object mutex = new Object(); 
    
    public mutex(Object mutex) {
        this.mutex = mutex; 
    }
    
    public void step1() throws InterruptedException {
        System.out.println("acquiring lock"); 
        synchronized(mutex) {
            System.out.println("got in sync block"); 
            System.out.println("calling wait"); 
            mutex.wait(); 
            System.out.println("wait finished "); 
        }
    }
    
    public void step2() throws InterruptedException{
        System.out.println("acquiring lock");
        synchronized(mutex){
            System.out.println("got in sync block"); 
            System.out.println("calling notify"); 
            mutex.notify();
            System.out.println("notify called"); 
        }
    }
}

测试场景:

  • 用两个独立线程分别执行step1和step2时,程序正常运行并输出预期结果;
  • 但在同一线程先调用step1、再sleep后调用step2的场景中,程序调用wait()后直接挂起。

我有以下两个疑问:

  1. 为何单线程场景会挂起?明明调用wait()时会释放锁。
  2. 是否必须使用独立线程才能正确使用wait()和notify()?

问题1:单线程场景挂起的原因

  • 核心逻辑:wait()会让当前线程释放锁并进入该对象的等待队列,必须由其他线程调用同一对象的notify()/notifyAll()才能唤醒它。
  • 在单线程流程里,当执行到step1中的mutex.wait()时,当前线程直接进入挂起状态,后续的sleep和step2调用根本没有机会执行——线程已经停在wait这一步了,没人能唤醒它,自然会一直挂起。
  • 你误以为wait()释放锁后线程会继续往下走,但实际上wait()是让线程暂停执行,只有其他线程的唤醒信号才能让它从wait()处恢复。

问题2:是否必须用独立线程?

  • 是的,wait()和notify()的设计初衷就是多线程间的协作通信,用来实现线程间的信号传递。
  • 单线程环境下使用这两个方法没有任何意义:挂起的线程无法自我唤醒,最终只会陷入永久挂起的状态。只有当存在其他持有同一锁对象的线程,并且该线程调用notify()/notifyAll()时,等待队列中的线程才有机会被唤醒并继续执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 16:35:27