4

Java问题:

退出同步块会自动执行 notifyAll()。这是预期的行为吗?

我已经对其进行了测试,它看起来像 1. 当执行超出同步块时,它会自动 notifyAll() 2. 当方法本身同步时,它会在返回时自动 notify()。(不是 notifyAll())

代码 :

public class Test {

    public static void main(String[] args) throws InterruptedException {

        MyThread lock = new MyThread();

        new WatingThread(lock,1).start();
        new WatingThread(lock,2).start();

        //above tow threads would start and then wait for a lock 


        lock.start();

    }
}

class MyThread extends Thread {

    public void run() {

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("MyThread is trying to acquire the lock ..");
        synchronized (this) {
            System.out.println("MyThread has acquired the lock !!");

            System.out.println("MyThread is Coming out of synch block..");
        }
        System.out.println("MyThread has released the lock !!");

    }
}


class WatingThread extends Thread
{
    private Object lock;
    private int id;

    public WatingThread(Object lock, int id )
    {
        this.lock = lock;
        this.id = id;
    }

    @Override
    public void run() {
        System.out.println(String.format("[%d] : Check if lock is available ...",new Object[]{id}));
        synchronized (lock) {
            System.out.println(String.format("[%d] : Acquired the lock !!",new Object[]{id}));
            try {
                System.out.println(String.format("[%d] : Going to wait on lock.. ",new Object[]{id}));
                lock.wait();
                System.out.println(String.format("[%d] : Got notified !!!",new Object[]{id}));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(String.format("[%d] :I am done !!",new Object[]{id}));
        }
    }


}

输出:

[2]:检查锁是否可用...
[2]:获得锁!
[1] : 检查锁是否可用...
[2] : 等待锁..
[1] : 获得锁!!
[1] : 正在等待锁..
MyThread 正在尝试获取锁..
MyThread 已获取锁!
MyThread 正在脱离同步块..
MyThread 已释放锁定!
[1]:收到通知!!!
[1]:我完成了!
[2]:收到通知!!!
[2]:我完成了!

4

2 回答 2

6

您发现的是,java.lang.Thread它在内部使用等待设施,将自身用作锁。这记录在Thread.join()方法的描述中(可能不是最好的地方):

此实现使用以 为this.wait条件的调用循环this.isAlive。当一个线程终止时,该this.notifyAll方法被调用。建议应用程序不要在 Thread 实例上使用waitnotify或。notifyAll

顺便说一句,如果您使用 while 循环来检查等待条件是否按照最佳实践的要求发生了变化,那么这将保护您免受此类唤醒,但当然,最好还是使用 anObject作为锁。

于 2013-06-06T06:51:52.067 回答
4

您不应该将Thread对象用作锁定对象。查看更多有问题的解释java是否隐式通知等待线程?.

广告:Jon Skeet在那里讲话:) (这是上述链接问题中答案的直接链接。)

评论中还链接了另一个问题,现在我将使它更容易实现:谁以及何时在调用 thread.join() 时通知 thread.wait()?

于 2013-06-06T06:45:05.093 回答