chapter14_构建自定义的同步工具_2_使用条件队列
-
条件队列可以构建高效、高响应性的状态依赖类(wait时自动挂起, 不用像轮询方式一样费尽心机的选择sleep时间), 但是__容易不正确使用__
所以, 如果可能的话, 还是__尽可能用LinkedBlockingQueue, Latch, Semephore, FutureTask等__
-
条件谓词
(1) 定义
使某个操作成为状态依赖操作的前提条件
例如, BlockingQueue的take方法的条件谓词是: 缓存不为空
(2) 条件等待的三元组:
加锁、 条件谓词、 wait()方法
-
过早唤醒
(1) wait()方法的返回__未必表示线程正在等待的条件谓词已经为真__
1° 同一个条件队列可以关联多个条件谓词, 唤醒可能来自其他的条件谓词成真, 而不是等待的那个条件谓词成真
例如BoundedBuffer的this作为一个条件队列, 关联了2个条件谓词: 缓存不为空 / 缓存不为满
2° wait()可以假装返回
(2) 发出通知的线程调用notifyAll时条件谓词为真, 到重新获取锁时又变成了假
因此, 结论是每当线程从wait()返回后, 都要再次检查条件谓词是否为真
-
使用条件等待时的原则(Object.wait或Condition.await)
(1) 线程在执行前必须通过条件谓词为真的测试
(2) 在调用wait()之前测试条件谓词, 在wait()返回之后还要测试条件谓词
(3) 在while循环中调用wait(), 直到条件满足
(4) 确保使用与条件队列相关的锁来保护构成条件谓词的各个状态变量
(5) 调用wait, notify, notifyAll时确保持有条件队列相关的锁
(6) 在检查条件谓词之后、开始执行相应的操作之前, 不能释放锁
-
信号丢失
示例: 一个条件队列关联两个条件谓词A、B, 两个线程分别等待A、B成真, 另一个线程调用notify(), 等待A的线程被唤醒, 重新测试条件谓词发现是A没有成真, 而是B成真导致发出的notify信号, 所以等待A的线程继续wait; 而本应该被唤醒的等待B的线程没有唤醒信号, 所以它只能继续等
结论: 尽可能使用notifyAll, 而不是notify
但是, notifyAll更低效, 因为绝大部分被唤醒的线程很可能继续等, 而且它们还要竞争锁, 但是要先保证程序运行正确再考虑优化, 所以还是先用notifyAll
-
什么时候可以放心大胆的使用notify
同时满足以下两个条件:
1° 所有等待线程的类型相同(不能有些线程等待缓存非空, 有些线程等待缓存非满)
2° 在条件变量上的每次通知, 最多只能唤醒一个线程来执行(例如生产好一个产品之后, 只能有一个消费者线程消费)
-
入口协议: 某个操作的条件谓词
出口协议: 该操作修改的所有状态变量, 并确认它们是否可以使其他的条件谓词变为真, 如果为真则notify
- 深度学习2017成果展
- Python正则表达式中的re.S的作用
- 图片转文字居然这么简单,多亏了这几个神器!
- 三、请求库之requests模块
- 升级 微信技术输出 时尚新门店尝鲜刷脸支付
- WSP Global品牌升级 启用3声母域名
- 一、爬虫基本原理
- python 中__setattr__, __getattr__,__getattribute__, __call__使用方法
- 量子技术与人工智能:同时进化的双生子
- TCP协议三次握手与四次挥手通俗解析
- Silverlight/aspx/ajax/mvc的UI自动化测试
- Office Open XML学习(1)-创建excel文档,并向单元格中插入字符串
- PyMC3和Theano代码构建贝叶斯深度网络,61页PPT探索贝叶斯深度学习以及实现
- 男程序员是不是都不会和女生表达交流?程序员的回答歪了
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- [HTTP趣谈]支持跨域及相关cookie设置
- pytest封神之路第三步 精通fixture
- 前端网络高级篇(六)网站性能优化
- 使用Webrtc和React Js在网络上共享跨平台的点对点文件
- JSBridge小科普
- Greenplum编译安装
- 宏任务和微任务到底是什么?
- React中的setState是异步的吗?
- java安全编码指南之:堆污染Heap pollution
- ECMAScript6基础学习教程(五)对象
- React入门系列(三)创建组件
- prometheus学习笔记(2)-利用java client写入数据
- Vue入门系列(一)Vue技术栈
- Openwrt智能路由系统开发--内容总结
- 干爆红队-爆破CS Teamserver 密码