zoukankan      html  css  js  c++  java
  • 《Java并发编程实战》第十四章 构建自己的同步工具定义 札记


    一、状态依赖性的管理

    有界缓存实现的基类
    @ 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
  • 相关阅读:
    python基础(6)---set、collections介绍
    Vue Router滚动行为 scrollBehavior
    CSS expression属性
    定时器setTimeout实现函数节流
    axios封装
    vue项目结构
    搭建vue项目环境
    javascript参数传递中处理+号
    微信支付 chooseWXPay:fail
    微信支付get_brand_wcpay_request:fail
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5030032.html
Copyright © 2011-2022 走看看