1

我有以下代码:

   public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        ThreadImpl thr = new ThreadImpl();
        thr.start();
        Thread.sleep(1000);
        synchronized(thr){
            System.out.println( "MAIN "+thr.hashCode());
            System.out.println("Main -->got the lock");
            thr.wait();
            System.out.println("Main -->Done with waiting");
        }
    }
}

class ThreadImpl extends Thread{
    public synchronized void sayHello(){
        System.out.println("Ssay hello ");
    }
    @Override
    public void run() {
        synchronized(this){
            System.out.println( "METHOD "+this.hashCode());
            System.out.println("METHOD Got the lock ");
            System.out.println("METHOD Going for sleep ");
                for(int i =0;i< 100000;i++);
            try {
                Thread.sleep(2000);
                System.out.println("METHOD Woke up ");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("METHOD Done leaving the thread");
        }
    }
}

在 ThreadDemo 的 main 方法中,我正在创建一个线程对象 ThreadImpl 并启动它。接下来,主线程休眠 1000ms。线程的 run 方法将在一个单独的线程中执行。作为其中的一部分,它循环 100000 次并休眠 2000ms。然后它退出该方法。主线程唤醒并获取“thr”的锁,然后进入等待状态。由于另一个线程已经完成了它的执行,这个等待应该是永远的。但是,我看到以下结果:

METHOD 1729414014 METHOD Get
the lock
METHOD Going for sleep
METHOD Woke up
METHOD Done leave the thread
MAIN 1729414014
Main --> 得到锁
Main --> 完成等待

在没有人通知的情况下,main 方法如何继续执行?

4

1 回答 1

0

这是虚假唤醒,请参阅jls

由于以下任一操作,线程可能会从等待集中移除,并将在之后的某个时间恢复:

  • 正在对 m 执行通知操作,其中 t 被选择从等待集中移除。
  • 在 m 上执行的 notifyAll 操作。
  • 对 t 执行的中断操作。
  • 如果这是一个定时等待,则从 m 的等待集合中删除 t 的内部动作发生在从这个等待动作开始后至少毫秒毫秒加上纳秒纳秒之后。
  • 执行的内部操作。尽管不鼓励实现,但允许执行“虚假唤醒”,即从等待集中删除线程,从而在没有明确指令的情况下启用恢复
于 2018-03-29T14:02:35.977 回答