一、状态依赖性的管理

有界缓存实现的基类
@ 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. Linux新手命令

    给老婆写了一份速成培训教材--最经常使用的命令及解释.当然每一个人工作内容不同,经常使用命令也不同,这仅仅是我的个人经验,并且要考虑到接受者的基础. ls:列出文件夹下的内容,类似于dos下的dir. ...

  2. iOS缓存类的设计

    使用执行速度缓存的程序可以大大提高程序,设计一个简单的缓存类并不需要太复杂的逻辑. 只需要一个简单的3接口. 存款对象 以一个对象 删除对象 阅读对象 watermark/2/text/aHR0cDo ...

  3. Heibernate 入门笔记(一)---第一个demo

    最近在学heibernate,是看马士兵老师的视频学的,在这里总结一下,做点笔记.关于heibernate的优点,大家可以在网上 百度,这里不做赘述,直接讲怎么使用heibernate 步骤一:新建项 ...

  4. Android 省市县 三级联动(android-wheel的使用)

    转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/23382805 今天没事跟群里面侃大山,有个哥们说道Android Wheel这个 ...

  5. 两个文件中的配置项设置方法和C比较程序处理

    在实际的软件开发项目.程序经常需要翻阅了一些资料可能会改变从外部,我们需要读出的信息到一个统一的文件(一般ini档),而此文件被称为个人资料. 考虑这样一个场景,程序须要与多个数据库打交道,要从配置文 ...

  6. 乐在其中设计模式(C#) - 组合模式(Composite Pattern)

    原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:weba ...

  7. Mybatis深入之事务管理

    Mybatis之事务管理 简单介绍 Mybatis的事务管理分为两种JdbcTransaction.ManagedTransaction. 当中JdbcTransaction仅仅是对数据库连接Conn ...

  8. MapReduce 规划 六系列 MultipleOutputs采用

    在前面的示例,输出文件名是默认: _logs part-r-00001 part-r-00003 part-r-00005 part-r-00007 part-r-00009 part-r-00011 ...

  9. SpringMVC Ajax返回的请求json 的方式来解决在中国字符串乱码问题

    1.org.springframework.http.converter.StringHttpMessageConverter类是类处理请求或相应的字符串.和默认字符集ISO-8859-1,所以当返回 ...

  10. 【原创】构建高性能ASP.NET站点之一 剖析页面的处理过程(前端)

    原文:[原创]构建高性能ASP.NET站点之一 剖析页面的处理过程(前端) 构建高性能ASP.NET站点之一 剖析页面的处理过程(前端) 前言:在对ASP.NET网站进行优化的时候,往往不是只是懂得A ...