(转)为什么wait(),notify()和notifyAll()必须在同步块或同步方法中调用

我们常用wait(),notify()和notifyAll()方法来进行线程间通信。线程检查一个条件后就行进入等待状态,例如,在“生产者-消费者”模型中,生产者线程发现缓冲区满了就等待,消费者线程通过消费一个产品使得缓冲区有空闲并通知生产者线程。notify()或notifyAll()的调用给一个或多个线程发出通知,告诉它(它们)条件已经发生改变,并且,一旦通知线程离开同步块,所有等待这个对象锁的线程将竞争这个对象锁,幸运的线程获得锁后就从wait()方法返回并继续执行。让我们把这整个操作分成几步来看看wait()和notify()方法之间的竞争条件(race condition),我们将使用“生产者-消费者”模型以便更容易理解这个场景:

  1. 生产者线程测试条件(缓冲区是否已满)并确定必须等待(发现缓冲区满后)
  2. 消费者线程从缓冲区消费一个产品后设置条件
  3. 消费者线程调用notify()方法,由于生产者线程此时还没有等待,这个消息将被忽略。
  4. 生产者线程调用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块中才有意义(否则,如果大家并不遵循同步机制,那还等谁呢?根本没人排队,也就谈不上等待和唤醒

时间: 2024-11-04 18:25:23

(转)为什么wait(),notify()和notifyAll()必须在同步块或同步方法中调用的相关文章

为什么wait(),notify()和notifyAll()必须在同步块或同步方法中调

我们常用wait(),notify()和notifyAll()方法来进行线程间通信.线程检查一个条件后就行进入等待状态,例如,在"生产者-消费者"模型中,生产者线程发现缓冲区满了就等待,消费者线程通过消费一个产品使得缓冲区有空闲并通知生产者线程.notify()或notifyAll()的调用给一个或多个线程发出通知,告诉它(它们)条件已经发生改变,并且,一旦通知线程离开同步块,所有等待这个对象锁的线程将竞争这个对象锁,幸运的线程获得锁后就从wait()方法返回并继续执行.让我们把这整个

解释为什么wait()和notify(), notifyAll()要放在同步块中

首先,wait()是释放锁的,因此wait()之前要先获得锁,而锁在同步块开始的时候获得,结束时释放,即同步块内为持有锁的阶段. 那为什么要设计同步块呢?或者说没有同步块会怎样呢? 原文地址:https://www.cnblogs.com/AllenDuke/p/12367556.html

Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者交出对临界资源的占用权,并进入挂起状态.然后等待消费者消费了商品,然后消费者通知生产者队列有空间了.同样地,当

多线程之线程间协作的两种方式:wait、notify、notifyAll和Condition

Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者交出对

thread_线程间协作:wait、notify、notifyAll和Condition

经典模式:生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者交出对临界资源的占用权,并进入挂起状态.然后等待消费者消费了商品,然后消费者通知生产者队列有空间了.同样地,当队列空时,消费者也必须等待,等待生产者通知它队列中有商品了.这种互相通信

19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者交出对

object的wait()、notify()、notifyAll()、方法和Condition的await()、signal()方法

wait().notify()和notifyAll()是 Object类 中的方法 从这三个方法的文字描述可以知道以下几点信息: 1)wait().notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写. 2)调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁) 3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个

Java并发之线程间协作Object的wait()、notify()、notifyAll()

wait().notify()和notifyAll()是Object类中的方法: 1)wait().notify()和notifyAll()方法是本地方法,而且为final方法,无法被重写. 2)调用某个对象的wait()方法能让当前线程堵塞.而且当前线程必须拥有此对象的monitor(即锁) 3)调用某个对象的notify()方法可以唤醒一个正在等待这个对象的monitor的线程,假设有多个线程都在等待这个对象的     monitor.则仅仅能唤醒当中一个线程: 4)调用notifyAll(

14 线程间协作的两种方式:wait、notify、notifyAll和Condition

原文链接:http://www.cnblogs.com/dolphin0520/p/3920385.html 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者