我们常用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://www.mamicode.com/info-detail-942381.html

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

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

    我们常用wait(),notify()和notifyAll()方法来进行线程间通信.线程检查一个条件后就行进入等待状态,例如,在“生产者-消费者”模型中,生产者线程发现缓冲区满了就等待,消费者线程通过 ...

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

    首先,wait()是释放锁的,因此wait()之前要先获得锁,而锁在同步块开始的时候获得,结束时释放,即同步块内为持有锁的阶段. 那为什么要设计同步块呢?或者说没有同步块会怎样呢?

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

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  4. wait、notify、notifyAll和Condition

    wait().notify()和notifyAll()是基于synchronized Condition是基于Lock的. Condition是在java 1.5中才出现的,它用来替代传统的Objec ...

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

    wait().notify()和notifyAll()是 Object类 中的方法 从这三个方法的文字描述可以知道以下几点信息: 1)wait().notify()和notifyAll()方法是本地方 ...

  6. Java并发编程(十三)线程间协作的两种方式:wait、notify、notifyAll和Condition

    在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果 ...

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

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

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

    原文链接:http://www.cnblogs.com/dolphin0520/p/3920385.html 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者- ...

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

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

随机推荐

  1. Js中的window.parent ,window.top,window.self ,window.openner详解

    在应用有frameset或者iframe的页面时,parent是父窗口,top是最顶级父窗口(有的窗口中套了好几层frameset或者iframe),self是当前窗口, opener是用open方法 ...

  2. OpenJudge计算概论-发票统计

    /*====================================================================== 发票统计 总时间限制: 1000ms 内存限制: 65 ...

  3. ajax重构XMLHttpRequest

    //重构XMLHttpRequestvar net = new Object(); //名字空間對象 net.READY_STATE_UNINITIALIZED = 0; net.READY_STAT ...

  4. sql常用语句--转载

    一.基础 .说明:创建数据库 CREATE DATABASE database-name .说明:删除数据库 drop database dbname .说明:备份sql server --- 创建 ...

  5. 【linux】umask

    1.默认情况下的umask值是022 [root@andon ~]# umask 0022  2.umask作用 默认文件权限:666(linux创建文件默认无执行权限)-umask =644(6-0 ...

  6. 【python】浅谈enumerate 函数

    enumerate 函数用于遍历序列中的元素以及它们的坐标: >>> for i,j in enumerate(('a','b','c')):  print i,j 0 a 1 b ...

  7. 使用express搭建第一个Web应用【Node.js初学】

    来源:http://jingyan.baidu.com/article/bad08e1ee501e009c8512106.html express是一个开源的node.js项目框架,初学者使用expr ...

  8. 49. Group Anagrams

    Given an array of strings, group anagrams together. For example, given: ["eat", "tea& ...

  9. activiti自定义流程之Spring整合activiti-modeler5.16实例(九):历史任务查询

    注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建        (2)创建流程模型:activiti自定义流程之Spring ...

  10. 我的Android最佳实践之—— Android启动画面的实现方法

    本文实例讲述了Android启动画面的实现方法.分享给大家供大家参考.具体分析如下: 在应用程序中经常用到启动画面,会启动一个后台线程为主程序的运行准备资源.Android要实现启动画面可以这样做: ...