《Java併發編程實戰》第十四章 構建本身的同步工具定義 札記


1、狀態依賴性的管理

有界緩存實現的基類
@ 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;
      }
}

2、使用條件隊列

1 條件謂詞
要想正確地使用條件隊列。關鍵是找出對象在哪一個條件謂詞上等待。

2 過早喚醒
好比:內置條件隊列中有多個條件謂語,此時假設調用notifyAll其含義是通知所有wait,但是並不必定所有條件謂語都知足運行條件。


當使用條件等待時(好比Object.wait或Condition.await):
. 一般都有一個條件謂詞--包含一些對象狀態的測試。線程在運行前必須首先經過這些測試。
. 在調用wait以前測試條件謂詞。並且從wait中返回時再次進行測試。


. 在一個循環中調用wait。
. 確保使用與條件隊列相關的鎖來保護構成條件謂詞的各個狀態變量。
. 當調用wait、notify或notifyAll等方法時。必定要持有與條件隊列相關的鎖。
. 在檢查條件謂詞以後以及開始運行對應的操做以前,不要釋放鎖。java


3 丟失的信號
已經知足通知的條件發出通知。但是以後才進入堵塞wait狀態。因此wait永遠等不到在其前面發出的notify。


4 通知
5 演示樣例:閥門類
6 子類的安全問題
7 封裝條件隊列
8 入口協議與出口協議

3、顯式的Condition對象 4、Synchronizer剖析 5、AbstractQueuedSynchronizer 6、java.util.concurrent同步器類 AQS 1 ReentrantLock 2 Semaphore與CountDownLatch 3 FutureTask 4 ReentrantReadWriteLock
相關文章
相關標籤/搜索