共享监视器对象时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
具体执行流程
- Thread-0启动后,获取
testString的锁,进入同步块,打印等待状态信息,然后调用wait()——此时Thread-0释放锁,进入等待队列。 - Thread-1此时可以获取到
testString的锁,进入同步块,执行同样的操作,打印信息后调用wait()释放锁。 - 后续Thread-2、3、4依次重复这个过程,直到所有5个线程都进入等待队列。
- main线程执行
synchronized (testString)获取锁,调用notify()——随机唤醒等待队列中的一个线程(这里是Thread-0)。 - Thread-0被唤醒后,需要重新获取
testString的锁(此时main线程已经释放锁),获取成功后继续执行wait()之后的代码,打印完成信息,最终退出同步块,执行后续输出。
结论
你看到多个线程进入同步块是完全符合Java多线程机制的,因为wait()会主动释放锁。而你的代码其实已经验证了notify()的特性——它只会唤醒等待队列中的一个线程,其他线程仍处于等待状态(如果需要唤醒所有线程,应该用notifyAll())。
内容的提问来源于stack exchange,提问作者potterhead
相关产品推荐
相关产品推荐

