生产者消费者模式中条件判断是使用while而不是if
永远在循环(loop)里调用 wait 和 notify,不是在 If 语句现在你知道wait应该永远在被synchronized的背景下和那个被多线程共享的对象上调用,下一个一定要记住的问题就是,你应该永远在while循环,而不是if语句中调用wait。因为线程是在某些条件下等待的——在我们的例子里,即“如果缓冲区队列是满的话,那么生产者线程应该等待”,你可能直觉就会写一个if语句。但if语句存在一些微妙的小问题,导致即使条件没被满足,你的线程你也有可能被错误地唤醒。所以如果你不在线程被唤醒后再次使用while循环检查唤醒条件是否被满足,你的程序就有可能会出错——例如在缓冲区为满的时候生产者继续生产数据,或者缓冲区为空的时候消费者开始消耗数据。所以记住,永远在while循环而不是if语句中使用wait!
因为在多核处理器环境中,Signal唤醒操作可能会激活多于一个线程(阻塞在条件变量上的线程),使得多个调用等待的线程返回。所以用while循环对condition多次判断,可以避免这种假唤醒。
基于以上认知,下面这个是使用wait和notify函数的规范代码模板:
// The standard idiom for calling the wait method in Java
synchronized(sharedObject) {
while(condition) {
sharedObject.wait();
// (Releases lock, and reacquires on wakeup)
}
// do action based upon condition e.g. take or put into queue
}
Ps:在while循环里使用wait的目的,是在线程被唤醒的前后都持续检查条件是否被满足。如果条件并未改变,wait被调用之前notify的唤醒通知就来了,那么这个线程并不能保证被唤醒,有可能会导致死锁问题。
注意:
- 永远在synchronized的方法或对象里使用wait、notify和notifyAll,不然Java虚拟机会生成 IllegalMonitorStateException。
- 永远在while循环里而不是if语句下使用wait。这样,循环会在线程睡眠前后都检查wait的条件,并在条件实际上并未改变的情况下处理唤醒通知。
- 永远在多线程间共享的对象(在生产者消费者模型里即缓冲区队列)上使用wait。
生产者消费者模式中条件判断是使用while而不是if的更多相关文章
- Java笔记1 : 在生产者消费者模式中,线程通信与共享数据,死锁问题与解决办法
本例定义了4个类,这里说一下,方便下面讲解.分别是Product(产品),Producer(生产者),Consumer(消费者), Test(测试类). 多线程之间通信与共享数据只要引用同一内存区域就 ...
- java ReentrantLock结合条件队列 实现生产者-消费者模式 以及ReentratLock和Synchronized对比
package reentrantlock; import java.util.ArrayList; public class ProviderAndConsumerTest { static Pro ...
- 使用BlockingQueue的生产者消费者模式
BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利.使用场景. 首先它是一个队列,而一个队 ...
- Java并发程序设计(十一)设计模式与并发之生产者-消费者模式
设计模式与并发之生产者-消费者模式 生产者-消费者模式是一个经典的多线程设计模式.它为多线程间的协作提供了良好的解决方案.在生产者-消费者模式中,通常由两类线程,即若干个生产者线程和若干个消费者线程. ...
- 关于java中生产者消费者模式的理解
在说生产者消费者模式之前,我觉得有必要理解一下 Obj.wait(),与Obj.notify()方法.wait()方法是指在持有对象锁的线程调用此方法时,会释放对象锁,同时休眠本线程.notify() ...
- 10 阻塞队列 & 生产者-消费者模式
原文:http://www.cnblogs.com/dolphin0520/p/3932906.html 在前面我们接触的队列都是非阻塞队列,比如PriorityQueue.LinkedList(Li ...
- 转:Task任务调度实现生产者消费者模式
我们经常会遇到生产者消费者模式,比如前端各种UI操作事件触发后台逻辑等.在这种典型的应用场景中,我们可能会有4个业务处理逻辑(下文以P代表生产者,C代表消费者): 1. FIFO(先进先出) ...
- Java设计模式—生产者消费者模式(阻塞队列实现)
生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...
- Java 生产者消费者模式详细分析
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
随机推荐
- ActiveMQ实战之 Queue点对点消息
前言:ActiveMQ消息模式点对点编码 运行:先运行消费者在开启消息生产者即可接收到消息 消息生产者 /** * @摘要 测试发送单条数据的类 */ public class ZMQOneSendT ...
- 20155205 《Java程序设计》0510课上实践博客
20155205 <Java程序设计>0510课上实践博客 一.教材代码检查-p98 未提交成功原因: 一开始在iterm中运行,但是结果出错,没有时间提交了.这个提交其实很简单,没有提交 ...
- .NET 开源GIS项目
SharpMapSharpMap是一个基于.NET 2.0使用C#开发的Map渲染类库,可以渲染ESRI Shape.PostGIS.MS SQL等格式的GIS数据,通过扩展地图数据Provider, ...
- HTML上传文件支持大文件上传,下载
上传 1.修改配置文件web.config,在<system.webServer>下面加入 <security> <requestFiltering > <r ...
- js基础学习笔记(零七)
indexOf() 方法 返回某个指定的字符串值在字符串中首次出现的位置. 语法: stringObject.indexOf(substring, startpos) 参数说明: 注意:如果要检索的字 ...
- 一份不太简短的LaTeX模板
编译环境: Ubuntu16.04 texllive2016 sublime text3 + latextools 该模板使用与自己写文档,记笔记,记录代码,写作业等等. %!TEX program ...
- [php-cookie] cookie 请求跨域,如何共享
cookie 请求跨域的问题, 假设我有两个域名,一个 m.example.com,另一个是 www.example.com . 那么我需要如何设置 cookie 才可以在这两个域名都实现共享呢? / ...
- 配置Info.plist (设置状态栏样式、自定义定位时系统弹出的提示语、配置3DTouch应用快捷菜单)
一.概述 iOS中很多功能需要配置Info.plist才能实现,如设置后台运行.支持打开的文件类型.自定义访问隐私内容时弹出的提示等.了解Info.plist中各字段及其含义,可以访问苹果开发网站相关 ...
- C#之WinForm设置控件居中
简单阐述 在C#的WinForm里面,原生控件是没有居中属性的,故通过重写OnResize(EventArgs e)方法,通过计算,重新定位控件位置. 以Label控件为例 (1)将label的Aut ...
- WPF概述(硬件加速及分辨率无关性)
一.名词解释 WPF(Windows Presentation Foundation),直译为Windows表示基础,是专门用来编写程序表示层的技术和工具. 大部分程序都是多层架构的,一般至少包含三层 ...