【Interview】深刻理解ReentrantLock

什麼是ReentrantLock

  • ReentrantLock是一個可重入的互斥鎖鎖, 實現Lock接口。具備與使用 synchronized 方法和語句所訪問的隱式監視器鎖相同的一些基本行爲和語義。ReentrantLock是顯示的獲取或釋放鎖,而且有鎖超時,鎖中斷等功能。java

  • 內部維戶了一個Sync的內部類,繼承AQS隊列同步器。git

  • ReentrantLock 將由最近成功得到鎖,而且尚未釋放該鎖的線程所擁有。當鎖沒有被另外一個線程所擁有時,調用 lock 的線程將成功獲取該鎖並返回。若是當前線程已經擁有該鎖,此方法將當即返回。可使用 isHeldByCurrentThread() 和 getHoldCount() 方法來檢查此狀況是否發生。github

  • 默認是非公平鎖的實現方式編程

非公平鎖獲取和釋放流程

加鎖併發

  • 執行lock方法加鎖時調用內部NonfairSynclock方法,第一次會快速嘗試獲取鎖,執行AQS類的compareAndSetState方法(CAS)更改同步狀態成員變量state,若是獲取成功 則設置當前線程爲鎖的持有者。失敗則執行AQS類的acquire方法,acquire會調用的AQS中的tryAcquire方法。這個tryAcquire方法須要自定義同步組件提供實現。
  • tryAcquire的具體流程是執行Sync類的nonfairTryAcquire方法:首先記錄當前加鎖線程,而後調用getState獲取同步狀態,若是爲0時 說明鎖處於空閒狀態,能夠獲取,會以CAS方式修改state變量。成功則設置當前線程 返回true。不然執行重入判斷,判斷當前訪問線程和已經持有鎖的線程是不是同一個。若是相同,將同步狀態值進行增長,並返回true。不然返回加鎖失敗false

解鎖函數

  • 解鎖unlock方法會調用內部類SynctryRelease方法。tryRelease首先調用getState方法獲取同步狀態,並進行了減法操做。在判斷釋放操做是否是當前線程,不是則拋出異常,而後判斷同步狀態是否等於0,若是是0,說明沒有線程持有,鎖是空閒的,則將當前鎖的持有者設置爲null, 方便其它線程獲取,並返回true。不然返回false

ReentrantLock經常使用方法介紹

  • getHoldCount() 查詢當前線程保持此鎖的次數。
  • getOwner() 返回目前擁有此鎖的線程
  • getQueueLength() 返回正等待獲取此鎖的線程估計數
  • getWaitingThreads(Condition condition) 返回一個 collection,它包含可能正在等待與此鎖相關給定條件的那些線程。
  • boolean hasQueuedThread(Thread thread) 查詢給定線程是否正在等待獲取此鎖。
  • boolean hasQueuedThreads() 查詢是否有些線程正在等待獲取此鎖。
  • boolean hasWaiters(Condition condition) 查詢是否有些線程正在等待與此鎖有關的給定條件
  • boolean isHeldByCurrentThread() 查詢當前線程是否保持此鎖。
  • void lock() 獲取鎖。
  • void lockInterruptibly() 若是當前線程未被中斷,則獲取鎖。
  • Condition newCondition() 返回用來與此 Lock 實例一塊兒使用的 Condition 實例。
  • boolean tryLock() 僅在調用時鎖未被另外一個線程保持的狀況下,才獲取該鎖。
  • void unlock() 釋放鎖

程序中使用源碼分析

private  ReentrantLock lock=new ReentrantLock();
    private  int i=0;
    public void a(){
        lock.lock();
        i++;
        lock.unlock();

    }
複製代碼

ReentrantLock源碼分析

package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.Collection;
public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;
    private final Sync sync;

    /**內部維護的一個幫助類,繼承成AQS 鎖的獲取和釋放主要靠它**/
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

    
        abstract void lock();

        /** * 執行非公平的t加鎖 */
        final boolean nonfairTryAcquire(int acquires) {
            //記錄當前加鎖線程
            final Thread current = Thread.currentThread();
            //獲取同步狀態 AQS中的volatile修飾的int類型成員變量 state 
            int c = getState();
            //爲0時 說明鎖處於空閒狀態,能夠獲取
            if (c == 0) {
                // CAS方式修改state。成功則設置當前線程 返回true
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //線程重入判斷,判斷當前訪問線程和已經持有鎖的線程是不是同一個
            else if (current == getExclusiveOwnerThread()) {
            //將同步狀態值進行增長

                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
				//設置同步狀態,重入鎖的話就累加,並返回true
                setState(nextc);
                return true;
            }
            return false;
        }
		//釋放鎖,就是把AQS中的同步狀態變量就行類減直到0 就是出於空閒狀態了
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            //若是釋放操做不是當前線程 則拋出異常
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            //同步狀態等於0,說明沒有線程持有,鎖是空閒的
            if (c == 0) {
                free = true;
                //當前鎖的持有者 設置爲null 方便其它線程獲取
                setExclusiveOwnerThread(null);
            }
          //若是該鎖被獲取了n次,那麼前(n-1)次tryRelease(int releases)方法必須返回false
            setState(c);
            return free;
        }
	
        protected final boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
            return new ConditionObject();
        }
        //返回目前擁有此鎖的線程,若是此鎖不被任何線程擁有,則返回 null。
        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }
		//查詢當前線程保持此鎖的次數。
        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
            
        //查詢鎖是否被持有
        final boolean isLocked() {
            return getState() != 0;
        }


        private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }

	//非公平的 Sync的子類
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        final void lock() {
            //第一次快速獲取鎖,使用CAS 方式 成功設置當前線程爲鎖的持有者
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                //鎖獲取失敗時,調用AQS的acquire去獲取鎖,
               //acquire會調用tryAcquire方法,tryAcquire須要自定義同步組件提供實現,
                //因此這裏的調用邏輯是acquire-》tryAcquire(NonfairSync類的)-》Sync的nonfairTryAcquire方法
                acquire(1);
        }
		//調用父類nonfairTryAcquire 實現加鎖
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }
	//公平的 Sync的子類
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;
		// 加鎖 調用AQS中的acquire方法,acquire會調用下面的tryAcquire方法
        final void lock() {
            acquire(1);
        }
		//加鎖的過程,和父類的調用父類nonfairTryAcquire方法大體同樣
        //惟一不一樣的位置爲判斷條件多了hasQueuedPredecessors()方法
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                //公平鎖實現的關鍵點hasQueuedPredecessors
                /** 即加入了同步隊列中當前節點是否有前驅節點的判斷 若是該方法返回true,則表示有線程比當前線程更早地請求獲取鎖 所以須要等待前驅線程獲取並釋放鎖以後才能繼續獲取鎖 */
                if (!hasQueuedPredecessors() && 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;
        }
    }
    //AQS中的方法 判斷當前線程是否位於CLH同步隊列中的第一個。若是是則返回true,不然返回false。
    public final boolean hasQueuedPredecessors() {
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        return h != t &&((s = h.next) == null || s.thread != Thread.currentThread());
    }
        
	//默認的構造函數 非公平鎖
    public ReentrantLock() { sync = new NonfairSync();}
    //爲true 公平鎖
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
    public void lock() { sync.lock();}
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }
    public boolean tryLock() { return sync.nonfairTryAcquire(1);}
    public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
	//釋放鎖
    public void unlock() {  sync.release(1);}
    public Condition newCondition() {return sync.newCondition();}
    public int getHoldCount() { return sync.getHoldCount(); }
    public boolean isHeldByCurrentThread() { return sync.isHeldExclusively();  }
    public boolean isLocked() {return sync.isLocked(); }
    public final boolean isFair() {   return sync instanceof FairSync;  }
    protected Thread getOwner() {return sync.getOwner(); }
    public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }

    public final boolean hasQueuedThread(Thread thread) { return sync.isQueued(thread);}
    public final int getQueueLength() { return sync.getQueueLength(); }
    protected Collection<Thread> getQueuedThreads() { return sync.getQueuedThreads(); }
    public boolean hasWaiters(Condition condition) {
        if (condition == null) throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
        return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
    }
    public int getWaitQueueLength(Condition condition) {
        if (condition == null) throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
        return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
    }
    protected Collection<Thread> getWaitingThreads(Condition condition) {
        if (condition == null) throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
        return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
    }

}

複製代碼
相關文章
相關標籤/搜索