(转)为什么wait(),notify()和notifyAll()必须在同步块或同步方法中调用
2017-08-19 16:05
423 查看
我们常用wait(),notify()和notifyAll()方法来进行线程间通信。线程检查一个条件后就行进入等待状态,例如,在“生产者-消费者”模型中,生产者线程发现缓冲区满了就等待,消费者线程通过消费一个产品使得缓冲区有空闲并通知生产者线程。notify()或notifyAll()的调用给一个或多个线程发出通知,告诉它(它们)条件已经发生改变,并且,一旦通知线程离开同步块,所有等待这个对象锁的线程将竞争这个对象锁,幸运的线程获得锁后就从wait()方法返回并继续执行。让我们把这整个操作分成几步来看看wait()和notify()方法之间的竞争条件(race condition),我们将使用“生产者-消费者”模型以便更容易理解这个场景:
生产者线程测试条件(缓冲区是否已满)并确定必须等待(发现缓冲区满后)
消费者线程从缓冲区消费一个产品后设置条件
消费者线程调用notify()方法,由于生产者线程此时还没有等待,这个消息将被忽略。
生产者线程调用wait()方法并进入等待状态。
因此,由于这里的竞争条件,我们可能在丢失一个通知,如果我们使用缓冲区或者只有一个产品,生产者线程将永远等待,你的程序也就挂起了。
现在我们考虑下这个潜在的竞争条件怎么解决。可以通过使用Java提供的synchronized关键字和锁来解决这个竞争条件。为了调用wait(),notify()和notifyAll()方法,我们必须获取调用这些方法的对象上的锁。由于wait()方法在等待前释放了锁并且在wait()方法返回之前重新获得了锁,我们必须使用这个锁来确保检查条件(缓冲区是否已满)和设置条件(从缓冲区取产品)是原子的,而这可以通过同步块或者同步方法实现。
简而言之,我们从同步块或者同步方法中调用wait(),notify()和notifyAll()方法可以避免:
IllegalMonitorStateException,如果我们不通过同步环境(synchronized context)调用这几个方法,系统将抛出此异常
wait()和notify()之间任何潜在的竞争条件。
说明:省略了原文中一些无关紧要的段落。
原文地址: http://javarevisited.blogspot.com/2011/05/wait-notify-and-notifyall-in-java.html 简单粗暴点:
wait是让使用wait方法的对象等待,暂时先把对象锁给让出来,给其它持有该锁的对象用,其它对象用完后再告知(notify)等待的那个对象可以继续执行了,因此,只有在synchronized块中才有意义(否则,如果大家并不遵循同步机制,那还等谁呢?根本没人排队,也就谈不上等待和唤醒了
生产者线程测试条件(缓冲区是否已满)并确定必须等待(发现缓冲区满后)
消费者线程从缓冲区消费一个产品后设置条件
消费者线程调用notify()方法,由于生产者线程此时还没有等待,这个消息将被忽略。
生产者线程调用wait()方法并进入等待状态。
因此,由于这里的竞争条件,我们可能在丢失一个通知,如果我们使用缓冲区或者只有一个产品,生产者线程将永远等待,你的程序也就挂起了。
现在我们考虑下这个潜在的竞争条件怎么解决。可以通过使用Java提供的synchronized关键字和锁来解决这个竞争条件。为了调用wait(),notify()和notifyAll()方法,我们必须获取调用这些方法的对象上的锁。由于wait()方法在等待前释放了锁并且在wait()方法返回之前重新获得了锁,我们必须使用这个锁来确保检查条件(缓冲区是否已满)和设置条件(从缓冲区取产品)是原子的,而这可以通过同步块或者同步方法实现。
简而言之,我们从同步块或者同步方法中调用wait(),notify()和notifyAll()方法可以避免:
IllegalMonitorStateException,如果我们不通过同步环境(synchronized context)调用这几个方法,系统将抛出此异常
wait()和notify()之间任何潜在的竞争条件。
说明:省略了原文中一些无关紧要的段落。
原文地址: http://javarevisited.blogspot.com/2011/05/wait-notify-and-notifyall-in-java.html 简单粗暴点:
wait是让使用wait方法的对象等待,暂时先把对象锁给让出来,给其它持有该锁的对象用,其它对象用完后再告知(notify)等待的那个对象可以继续执行了,因此,只有在synchronized块中才有意义(否则,如果大家并不遵循同步机制,那还等谁呢?根本没人排队,也就谈不上等待和唤醒了
相关文章推荐
- [转]java 为什么wait(),notify(),notifyAll()必须在同步方法/代码块中调用?
- 为什么wait(),notify(),notifyAll()必须在同步方法/代码块中调用?
- java 为什么wait(),notify(),notifyAll()必须在同步方法/代码块中调用?
- java 为什么wait(),notify(),notifyAll()必须在同步方法/代码块中调用?
- java 为什么wait(),notify(),notifyAll()必须在同步方法/代码块中调用?
- 为什么wait(),notify(),notifyAll()必须在同步方法/代码块中调用?
- 为什么wait(),notify()和notifyAll()必须在同步块或同步方法中调
- 为什么Object.wait(),Object.notify(),Object.notifyAll()必须在同步块中执行呢?
- 协调同步的线程方法 wait,notifyAll,notify
- wait() ,notify() ,notifyAll(),synchronized 和同步方法锁,对象锁的联系,关系,区别;
- 为什么wait, notify 和 notifyAll这些方法不在thread类里面?
- (wait()或者notify()必须采用当前锁调用 ) && (类.方法VS对象.方法)
- java notify()、 notifyAll()、 wait()、sleep()、yield()、join()方法学习
- 最简实例说明wait、notify、notifyAll的使用方法
- Thread_wait、notify、notifyAll的使用方法
- 又踩.NET Core的坑:在同步方法中调用异步方法Wait时发生死锁(deadlock)
- Java线程中sleep()、wait()和notify()和notifyAll()、yield()、join()等方法的用法和区别
- wait()、notify()和notifyAll()是 Object类 中的方法
- 最简实例说明wait、notify、notifyAll的使用方法
- 最简实例说明wait、notify、notifyAll的使用方法