【Interview】深入理解ReentrantLock

codeing_docs發表於2019-03-20

什麼是ReentrantLock

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

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

  • ReentrantLock 將由最近成功獲得鎖,並且還沒有釋放該鎖的執行緒所擁有。當鎖沒有被另一個執行緒所擁有時,呼叫 lock 的執行緒將成功獲取該鎖並返回。如果當前執行緒已經擁有該鎖,此方法將立即返回。可以使用 isHeldByCurrentThread() 和 getHoldCount() 方法來檢查此情況是否發生。

  • 預設是非公平鎖的實現方式

非公平鎖獲取和釋放流程

加鎖

  • 執行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);
    }

}

複製程式碼

相關文章