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

共享监视器对象时Synchronized关键字未按预期工作问题

关于wait()释放监视器锁的问题解析

你的问题核心是对wait()方法的锁机制理解有误——当线程调用wait()时,会主动释放它持有的监视器对象锁,这就是为什么多个线程能依次进入同步块的原因。

代码与输出分析

先看你的代码(修正了转义字符):

public class WaitAndNotifyTest {

    public static void main(String[] args) {
        Object testString = new Object();
        RunnableImplTest runnableImplTest = new RunnableImplTest(testString);
        for(int i=0; i<5; i++) {
            Thread thread = new Thread(runnableImplTest);
            System.out.println("Created thread " + thread.getName());
            thread.start();
        }
        
        synchronized (testString) {
            testString.notify();
        }

    }
    
    private static class RunnableImplTest implements Runnable{
        
        private Object str;
        
        public RunnableImplTest(Object str) {
            this.str = str;
        }

        @Override
        public void run() {
            try {
                synchronized (str) {
                    System.out.println("Sending in waiting state for thread "+Thread.currentThread().getName());
                    str.wait();
                    System.out.println("Waiting completion for thread " + Thread.currentThread().getName());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Got the control for "+Thread.currentThread().getName());
            
        }
        
    }

}

对应的输出:

Created thread Thread-0
Created thread Thread-1
Created thread Thread-2
Sending in waiting state for thread Thread-0
Created thread Thread-3
Sending in waiting state for thread Thread-1
Created thread Thread-4
Sending in waiting state for thread Thread-2
Sending in waiting state for thread Thread-3
Sending in waiting state for thread Thread-4
Waiting completion for thread Thread-0
Got the control for Thread-0

具体执行流程

  1. Thread-0启动后,获取testString的锁,进入同步块,打印等待状态信息,然后调用wait()——此时Thread-0释放锁,进入等待队列。
  2. Thread-1此时可以获取到testString的锁,进入同步块,执行同样的操作,打印信息后调用wait()释放锁。
  3. 后续Thread-2、3、4依次重复这个过程,直到所有5个线程都进入等待队列。
  4. main线程执行synchronized (testString)获取锁,调用notify()——随机唤醒等待队列中的一个线程(这里是Thread-0)。
  5. Thread-0被唤醒后,需要重新获取testString的锁(此时main线程已经释放锁),获取成功后继续执行wait()之后的代码,打印完成信息,最终退出同步块,执行后续输出。

结论

你看到多个线程进入同步块是完全符合Java多线程机制的,因为wait()会主动释放锁。而你的代码其实已经验证了notify()的特性——它只会唤醒等待队列中的一个线程,其他线程仍处于等待状态(如果需要唤醒所有线程,应该用notifyAll())。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 12:37:23