一、状态依赖性的管理

有界缓存实现的基类
@ ThreadSafe
public abstract class BaseBoundedBuffer<E> {
@GuardeBy( "this" ) private final E[] buf;
@GuardeBy( "this" ) private int tail;
@GuardeBy( "this" ) private int head;
@GuardeBy( "this" ) private int count; protected BaseBoundedBuffer( int capacity) {
this .buf = (E[]) new Object[capacity];
} protected synchronized final void doPut(E E) {
buf[tail] = E;
if (++tail == buf.length) {
tail = 0;
}
++count;
} protected synchronized final E doTake() {
E E = buf[head];
buf[head] = null ;
if (++head == buf.length) {
head = 0;
}
--count;
return E;
} public synchronized final boolean isFull() {
return count == buf.length;
} public synchronized final boolean isEmpty() {
return count == 0;
}
}

1 演示样例:将前提条件的失败传递给调用者
@ ThreadSafe
public class GrumpyBoundedBuffer<V> extends BaseBoundedBuffer<V> {
public GrumpyBoundedBuffer( int size){
super (size);
} public synchronized void put(V v){
if (isFull()){
throw new BufferFullException ();
}
doPut(v);
} public synchronized V take(){
if (isEmpty())
throw new BufferEmptyExeption ();
return doTake();
}
}

缓存为空或者已满都不是异常情况,使用者必需要捕获这些异常才干进行正确的处理。

       while (true ){
try {
V item = buffer.take();
// 对于item运行一些操作
break ;
} catch (BufferEmptyException e) {
Thread. sleep(SLEEP_GRANULARITY );
}
}



2 演示样例:通过轮询与休眠来实现简单的堵塞
从上面的代码能够看出,堵塞与出现异常都须要方法的使用者来处理,如今尝试都封装到有界缓存中。
@ ThreadSafe
public class SleepyBoundedBuffer<V> extends BaseBoundedBuffer<V> {
public SleepyBoundedBuffer( int size) {
super (size);
} public void put(V v) throws InterruptedException{
while (true ){
synchronized (this ){
if (!isFull()){
doPut(v);
return ;
}
}
Thread.sleep(SLEEP_GRANULARITY);
}
} public V take() throws InterruptedException{
while (true ){
synchronized (this ){
if (!isEmpty()){
return doTake();
}
}
Thread.sleep(SLEEP_GRANULARITY);
}
}
}


3 条件队列
不须要使用while(true),改为使用wait、notifyAll
@ ThreadSafe
public class BoundedBuffer<V> extends BaseBoundedBuffer<V> { // 条件谓词:not-full (!isFull())
// 条件谓词:not-empty (!isEmpty()) public BoundedBuffer( int size) {
super (size);
} // 堵塞并直道:not-full
public synchronized void put(V v) throws InterruptedException{
while (isFull()){
wait();
}
doPut(v);
notifyAll();
} // 堵塞并直道:not-empty
public synchronized V take() throws InterruptedException{
while (isEmpty()){
wait();
}
V v = doTake();
notifyAll();
return v;
}
}

二、使用条件队列

1 条件谓词

要想正确地使用条件队列。关键是找出对象在哪个条件谓词上等待。


2 过早唤醒
比如:内置条件队列中有多个条件谓语,此时假设调用notifyAll其含义是通知全部wait,可是并不一定全部条件谓语都满足运行条件。


当使用条件等待时(比如Object.wait或Condition.await):

. 通常都有一个条件谓词--包含一些对象状态的測试。线程在运行前必须首先通过这些測试。

. 在调用wait之前測试条件谓词。而且从wait中返回时再次进行測试。

. 在一个循环中调用wait。

. 确保使用与条件队列相关的锁来保护构成条件谓词的各个状态变量。

. 当调用wait、notify或notifyAll等方法时。一定要持有与条件队列相关的锁。

. 在检查条件谓词之后以及開始运行对应的操作之前,不要释放锁。



3 丢失的信号
已经满足通知的条件发出通知。可是之后才进入堵塞wait状态。所以wait永远等不到在其前面发出的notify。



4 通知

5 演示样例:阀门类

6 子类的安全问题

7 封装条件队列

8 入口协议与出口协议



三、显式的Condition对象

四、Synchronizer剖析

五、AbstractQueuedSynchronizer

六、java.util.concurrent同步器类 AQS

1 ReentrantLock

2 Semaphore与CountDownLatch

3 FutureTask

4 ReentrantReadWriteLock

《Java并发编程实战》第十四章 构建自己的同步工具定义 札记的更多相关文章

  1. 《java并发编程实战》读书笔记11--构建自定义的同步工具,条件队列,Condition,AQS

    第14章 构建自定义的同步工具 本章将介绍实现状态依赖性的各种选择,以及在使用平台提供的状态依赖机制时需要遵守的各项规则. 14.1 状态依赖性的管理 对于并发对象上依赖状态的方法,虽然有时候在前提条 ...

  2. java并发编程实战:第十四章----构建自定义的同步工具

    一.状态依赖性管理 对于单线程程序,某个条件为假,那么这个条件将永远无法成真 在并发程序中,基于状态的条件可能会由于其他线程的操作而改变 可阻塞的状态依赖操作的结构 acquire lock on o ...

  3. java并发编程实战:第四章----对象的组合

    一.设计线程安全的类 找出构造对象状态的所有变量(若变量为引用类型,还包括引用对象中的域) 约束状态变量的不变性条件 建立对象状态的并发访问管理策略(规定了如何维护线程安全性) 1.收集同步需求(找出 ...

  4. 《Java并发编程实战》第四章 对象的组合 读书笔记

    一.设计线程安全的类 在设计线程安全类的过程中,须要包括下面三个基本要素:  . 找出构成对象状态的全部变量.  . 找出约束状态变量的不变性条件.  . 建立对象状态的并发訪问管理策略. 分析对象的 ...

  5. 【Java并发编程实战】----- AQS(四):CLH同步队列

    在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形.其主要从两方面进行了改造:节点的结构与节点等待机制.在结构上引入了头 ...

  6. 【Java并发编程实战】—– AQS(四):CLH同步队列

    在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形. 其主要从双方面进行了改造:节点的结构与节点等待机制.在结构上引入了 ...

  7. 《Java并发编程实战》第三章 对象的共享 读书笔记

    一.可见性 什么是可见性? Java线程安全须要防止某个线程正在使用对象状态而还有一个线程在同一时候改动该状态,并且须要确保当一个线程改动了对象的状态后,其它线程能够看到发生的状态变化. 后者就是可见 ...

  8. java并发编程的艺术——第四章总结

    第四章并发编程基础 4.1线程简介 4.2启动与终止线程 4.3线程间通信 4.4线程应用实例 java语言是内置对多线程支持的. 为什么使用多线程: 首先线程是操作系统最小的调度单元,多核心.多个线 ...

  9. 《Java并发编程实战》第六章 任务运行 读书笔记

    一. 在线程中运行任务 无限制创建线程的不足 .线程生命周期的开销很高 .资源消耗 .稳定性 二.Executor框架 Executor基于生产者-消费者模式.提交任务的操作相当于生产者.运行任务的线 ...

随机推荐

  1. 调用API 清屏

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  2. 重新想象 Windows 8 Store Apps (32) - 加密解密: 非对称算法, 数据转换的辅助类

    原文:重新想象 Windows 8 Store Apps (32) - 加密解密: 非对称算法, 数据转换的辅助类 [源码下载] 重新想象 Windows 8 Store Apps (32) - 加密 ...

  3. onsubmit事件

    var oForm = document.getElementById("form1"); oForm.onsubmit = function(){   alert("你 ...

  4. 解决apache+tomcatserver环境中文乱码的问题

    在使用apache做转发服务器时,碰到了中文乱码的问题. 说说解决思路: 1.通常乱码是由于编码不统一造成的.所以要先推断是不是由于编码问题造成的,假设是的话,那统一编码就能够去解决. 2.tomca ...

  5. swift 笔记 (十二) —— 下标

    下标 swift同意我们为 类.结构体,枚举 定义下标,以更便捷的方式訪问一大堆属性.比方Array和Dictionary都是结构体,swift的project师已经为这两个类型提供好了下标操作的代码 ...

  6. Asp.NET MVC3 使用 SignalR 实现推(持续)

    一,Persistent Connection 演示示例教程 1.实现server端代码 1),编写server PersistentConnection 代码 项目中 SignalR 文件夹下创建 ...

  7. Andorid Async-HttpClient阅览

    Async-httpclient它是一个用于Android应用程序开发http访问开源框架.开源GitHub在,因为今天GitHub下载没有看到.我在这里提供下载地址.是之前从GitHub上下载的,版 ...

  8. 离PACKET_INp获取信息acket data

         于Floodlight模块假设要packet in消息,就对对应的消息类型进行监听就可以.然后在receive方法中就能够操纵这个上传上来的packet_in.      关键代码:   E ...

  9. mysql 多个字段拼接

    Mysql的查询结果行字段拼接,能够用以下两个函数实现: 1. concat函数 mysql> select concat('1','2','3') from test ; +--------- ...

  10. IBatis.Net获取执行的Sql语句

    前言 IBatis.Net中Sql语句是些在配置文件中的,而且配置文件是在程序启动时读取的(我们开发的时候需要将其设置成较新复制或者是始终复制),而不是程序将其包含在其中(例如NHibernate的映 ...