首页 文章

等待/通知的奇怪java行为

提问于
浏览
4

我发现java并发的奇怪行为 . 请参阅下面的代码:

public class Test {
        static CountDownLatch latch = new CountDownLatch(1);
        public static void main(String[] args) throws UnsupportedEncodingException, InterruptedException {
            final Thread t = new MyThread();
            t.start();
            synchronized (t) {
                latch.countDown();
                System.out.println("got to sleep");
                t.wait();
                System.out.println("wake up");
            }
        }

        static class MyThread extends Thread {
            @Override
            public void run() {
                try {
                    latch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (this) {
                    System.out.println("inside run");
    //                notifyAll();
                }
            }
        }
    }

在我看来,这段代码应该挂起并永远等待,但代码完成后没有任何问题,在控制台中下一步:

got to sleep
inside run
wake up

我试图找到一些关于通知锁的信息,如果线程死了,但缺乏它 . 另外我在java规范中找不到任何信息 .

但是,如果我试图锁定其他一些对象(不在线程对象上),它就像我预期的那样工作正常 .

2 回答

  • 0

    它's because you'等待 Thread 实例 . Thread 在内部使用 wait / notify / notifyAll ,所以你不应该't do that yourself as well - you' ll混淆 ThreadThread 会让你感到困惑 . 特别是,当一个线程退出时,它会调用 this.notifyAll() .

    Thread.join 的文档:

    此实现使用this.wait调用this.isAlive的循环 . 当一个线程终止时,将调用this.notifyAll方法 . 建议应用程序不要在Thread实例上使用wait,notify或notifyAll .

    通常,尝试锁定并等待没有其他任何东西可以与之交互的对象 . 这样你可以推断出对象上存在的与并发相关的操作,因为它们很难证明你的代码是正确的 . 那个's why you'经常会看到类似的东西:

    public class Foo {
        private final Object lock = new Object();
    
        ... code which uses synchronized(lock) ...
    }
    
  • 7

    正如Jon Skeet所写,在Thread对象上进行同步是个坏主意,请使用另一个:

    public class Test {
        static CountDownLatch latch = new CountDownLatch(1);
        static final Object sync = new Object();
    
        public static void main(String[] args) throws UnsupportedEncodingException, InterruptedException {
            final Thread t = new MyThread();
            t.start();
            synchronized (sync) {
                latch.countDown();
                System.out.println("got to sleep");
                sync.wait();
                System.out.println("wake up");
            }
        }
    }
    
    static class MyThread extends Thread {
        @Override
        public void run() {
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (sync) {
                System.out.println("inside run");
                //sync.notifyAll();
            }
        }
    }
    

    现在这个代码永远不会结束,直到你取消注释sync.notifyAll();

相关问题