wait / notify的奇怪java行为

我发现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规范中找到任何信息。

但是如果我试图锁定其他对象(而不是线程对象),它就像我期望的那样工作正常。


这是因为你在等待一个Thread实例。 Thread内部使用wait / notify / notifyAll ,所以你不应该自己这么做 - 你会混淆ThreadThread会混淆你。 特别是,当一个线程退出时,它会调用this.notifyAll()

Thread.join的文档:

这个实现使用this.wait调用的一个循环,条件是this.isAlive 。 当一个线程终止this.notifyAll方法被调用。 建议应用程序不要在Thread实例上使用waitnotifynotifyAll

一般来说,尝试锁定并等待没有其他东西可以互动的对象。 这样,您可以推断对象上存在的并发相关操作,因为它们非常有限。 一旦任意代码可以在对象上同步(并且调用wait / notify等),就很难证明你的代码是正确的。 这就是为什么你会经常看到像这样的东西:

public class Foo {
    private final Object lock = new Object();

    ... code which uses synchronized(lock) ...
}

正如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();否则此代码将永不结束。

链接地址: http://www.djcxy.com/p/91971.html

上一篇: Strange java behavior of wait/notify

下一篇: Volatile Vs Static in java