《Java并发编程实战》第十四章 构建自定义的同步工具 读书笔记

来源:互联网 发布:淘宝上卖的火麻能飞吗 编辑:程序博客网 时间:2024/06/03 16:33

一、状态依赖性的管理

有界缓存实现的基类
@ ThreadSafepublic 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 示例:将前提条件的失败传递给调用者
@ ThreadSafepublic 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 示例:通过轮询与休眠来实现简单的阻塞
从上面的代码可以看出,阻塞与出现异常都需要方法的使用者来处理,现在尝试都封装到有界缓存中。
@ ThreadSafepublic 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
@ ThreadSafepublic 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
2 0
原创粉丝点击