为什么wait / notify / notifyAll方法在java中不同步? [英] why wait/notify/notifyAll methods are not synchronized in java ?

查看:143
本文介绍了为什么wait / notify / notifyAll方法在java中不同步?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,每当我们需要调用wait / notify / notifyAll时,我们需要访问对象监视器(通过synchronized方法或通过synchronized块)。所以我的问题是为什么java没有去同步等待/通知方法去除从同步块或方法调用这些方法的限制。



如果这些声明为已同步,它将自动获取监视器访问权限。

解决方案

对于notify和notifyAll,你的想法的问题是,当你通知你还有其他你正常做的事情在同一个同步块中。因此,使notify方法同步不会给你任何东西,你仍然需要块。同样,等待必须在同步块或方法中才能有用,例如在自旋锁内,无论如何必须同步测试。所以锁定的粒度对你的建议都是错误的。



这是一个例子,这是关于Java中最简单的队列实现:

 公共类MyQueue< T> {

private List< T> list = new ArrayList< T>();

public T take()抛出InterruptedException {
synchronized(list){
while(list.size()== 0){
list.wait() ;
}
返回list.remove(0);
}
}

public void put(T object){
synchronized(list){
list.add(object);
list.notify();
}
}
}

所以你可以有生产者线程将事物添加到队列和消费者线程中。当一个线程从队列中获取某些内容时,它需要在synchronized块中检查列表中是否存在某些内容,并且一旦通知它,它需要重新获取锁定并确保列表中仍然存在某些内容(因为某些内容)其他的消费者线程可能已经介入并抓住了它。)还有虚假的唤醒现象:你不能依赖被唤醒作为发生事情的充分证据,你需要检查你正在等待的任何条件for实际上是真的,这需要在synchronized块中完成。



在这两种情况下,需要在锁定时进行等待检查当代码根据这些检查采取行动时,它知道这些结果当前是有效的。


in Java whenever we need to call wait/notify/notifyAll, we need to have access to object monitor (either through synchronized method or through synchronized block). So my question is why java didn't go for synchronized wait/notify methods removing the restriction of calling these methods from synchronized block or methods.

In case these are declared as synchronized, it would have automatically taken the monitor access.

解决方案

For notify and notifyAll, the problem with your idea is that when you notify you also have other stuff you're typically doing in the same synchronized block. So making the notify method synchronized wouldn't buy you anything, you'd still need the block. Likewise wait has to be in a synchronized block or method in order to be useful, such as being inside a spinlock where the test has to be synchronized anyway. So the granularity of locking is all wrong for what you suggest.

Here's an example, this is about the simplest queue implementation you can have in Java:

public class MyQueue<T> {

    private List<T> list = new ArrayList<T>();

    public T take() throws InterruptedException {
        synchronized(list) {
            while (list.size() == 0) {
                list.wait();
            }
            return list.remove(0);
        }
    }

    public void put(T object) {
        synchronized(list) {
            list.add(object);
            list.notify();
        }
    }
}

So you can have producer threads that add things to the queue and consumer threads that take things out. When a thread goes to get something out of the queue it needs to check within the synchronized block that there's something in the list, and once it's been notified it needs to reacquire the lock and make sure there is still something in the list (because some other consumer thread could have stepped in and grabbed it).There's also the "spurious wake-up" phenomenon: you can't rely on getting woken up as sufficient evidence that something happened, you need to check that whatever condition you're waiting for is actually true, and that needs to be done within the synchronized block.

In both of these cases, checks surrounding the wait need to be made with the lock held so that when the code takes action based on those checks it knows that those results are currently valid.

这篇关于为什么wait / notify / notifyAll方法在java中不同步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆