Reentranlock FairSync NonFairSync

 

對於Reentranlock的用法,對比Synchronized多了 定時守候、可中斷守候、公平和非公平。本文重點就Reentranlock 中的代碼實現作一個分析。而對於其與Synchronize 區別可參考下文。java

能夠參考深刻研究 Java Synchronize 和 Lock 的區別與用法http://my.oschina.net/softwarechina/blog/170859node

 FairSync NonFairSync  二者都是java.util.concurrent包中同步類中如Semaphere,Reentranlock 等類中的內部類,二者繼承自 AQS,而Reentranlock中的 二者代碼以下所示,爲獨佔模式。二者都實現了tryAcquire,與lock方法。less

 

static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

Reentranlock 根據參數,肯定使用哪一種同步器,默認是NonFairSync。從代碼分析出,NonFairSync最大的特色是,調用lock時,會先嚐試去獲取資源,而獲取不一樣,則經過父類的acquire(1)方法,調用各自子類的tryAcquire方法,以下。而對於NonFairSync,在一次執行父類Sync中的方法,在一次嘗試獲取資源。ui

然而對於FairSync的lock,直接調用acquire,少了一次直接獲取的過程,接着調用子類的tryAcquire方法,當有資源空閒時,並不像NonFair 直接嘗試get,而是先判斷當前線程是否隊列頭部的線程,或者是空的queue,則嘗試獲取。不然判斷當前線程是不是佔用資源的線程。若是是,則將state+1,表示該線程調了屢次lock,釋放時要調同等次數的unlock,才能釋放資源。.net

static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&  //當前Thread是不是head節點的next節點線程,由於公平的鎖,按順序獲取資源
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

    接着上一步,二者都沒有獲取到資源時,將執行同樣的流程,可是執行到tryAcqure方法時,會根據不一樣子類實現的來執行。線程

        以下代碼,首先code

  1.     addWaiter,,生成一個Exclusive模式的結點,並將當前結點加入到queque的尾部。若是原tail爲null,也就是queque爲null時,會cas一個new  Node,然後加到該node尾部。並作爲新的tail。
  2.     然後會 執行acquireQueued方法,根據node的 predocessor,判斷是否爲head,若是是則執行tryAcquire,  獲取成功後,將當前結點置爲head,並將thread置爲null,已經得到資源。
  3.    當node的prddocessor不爲head時,或者獲取失敗,接着會根據waitStatus,執行相關操做,最終state置爲Node.Signal,然後被阻塞,等着被unPark或者被中斷。
public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

 

而對於 Reentranlock 的其它功能如 中斷守候,超時等,都是針對這些條件作了額外的操做。orm

相關文章
相關標籤/搜索