java.util.concurrent.locks.ReentrantLock 源碼

ReentrantLock實現了lock接口,經過調用AbstractQueuedSynchronizer (AQS) 中的方法,實現了主要功能。html

 

相關類圖:

 

java.util.concurrent.locks.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;

    abstract static class Sync extends AbstractQueuedSynchronizer {
        //序列號  
        private static final long serialVersionUID = -5179523762034025860L;

        //獲取鎖方法,交由NonfairSync和FairSync實現
        abstract void lock();

        // 非公平方式獲取鎖,用於tryLock()方法
        final boolean nonfairTryAcquire(int acquires) {
            //當前線程
            final Thread current = Thread.currentThread();
            // 繼承至AbstractQueuedSynchronizer的方法
            int c = getState();//獲取鎖狀態值

            //沒有線程正在競爭該鎖
            if (c == 0) {
                // 繼承至AbstractQueuedSynchronizer的方法
                if (compareAndSetState(0, acquires)) {//若state爲0則將state修改成acquires的值,狀態0表示鎖沒有被佔用
                    //AbstractQueuedSynchronizer繼承至AbstractOwnableSynchronizer的方法
                    setExclusiveOwnerThread(current);// 設置當前線程獨佔
                    return true;// 成功
                }
            }
            else if (current == getExclusiveOwnerThread()) {// 當前線程擁有該鎖
                int nextc = c + acquires;// 增長重入次數
                if (nextc < 0) // overflow(計數值小於0,則拋出異常)
                    throw new Error("Maximum lock count exceeded");
                // 繼承至AbstractQueuedSynchronizer的方法
                setState(nextc);//設置鎖狀態值
                return true;// 成功
            }
            return false;// 失敗
        }

        // 試圖在共享模式下獲取對象狀態,此方法應該查詢是否容許它在共享模式下獲取對象狀態,若是容許,則獲取它
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread()) // 當前線程不爲獨佔線程
                throw new IllegalMonitorStateException(); // 拋出異常
            // 釋放標識
            boolean free = false; 
            if (c == 0) {
                free = true;
                // 已經釋放,清空獨佔
                setExclusiveOwnerThread(null); 
            }
            // 設置標識
            setState(c); 
            return free; 
        }

        // 判斷資源是否被當前線程佔有
        protected final boolean isHeldExclusively() {
            //AbstractQueuedSynchronizer繼承至AbstractOwnableSynchronizer的方法
            return getExclusiveOwnerThread() == Thread.currentThread();//判斷佔用資源的線程和當前線程是否一致
        }

        //新增一個條件隊列
        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        //返回資源的佔用線程對象
        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        //獲得鎖狀態值
        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;//若資源被當前線程佔用,返回狀態值;不然返回0.
        }

        //判斷資源是否被佔用
        final boolean isLocked() {
            return getState() != 0;
        }

        //自定義反序列化邏輯
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // 重置爲未鎖定狀態
        }
    }

    //非公平策略獲取鎖(每一次嘗試獲取鎖,都不會按照公平等待的原則,讓等待時間最久的線程得到鎖。)
    static final class NonfairSync extends Sync {
        // 版本號
        private static final long serialVersionUID = 7316153563782823691L;

        // 實現得到鎖的方法
        final void lock() {
            if (compareAndSetState(0, 1))//若state爲0則將state修改成acquires的值,狀態0表示鎖沒有被佔用
                // 把當前線程設置獨佔鎖
                setExclusiveOwnerThread(Thread.currentThread());
            else//鎖已經被佔用,或者set失敗
                //以獨佔模式獲取對象,忽略中斷
                acquire(1); 
        }

        //嘗試獲取鎖
        protected final boolean tryAcquire(int acquires) {
            //調用繼承至Sync的方法
            return nonfairTryAcquire(acquires);//非公平方式獲取鎖
        }
    }

    //公平策略獲取鎖
    static final class FairSync extends Sync {
        //版本序列化
        private static final long serialVersionUID = -3000897897090466540L;

        // 實現得到鎖的方法
        final void lock() {
            acquire(1);// 以獨佔模式獲取對象,忽略中斷
        }


        //嘗試公平獲取鎖
        protected final boolean tryAcquire(int acquires) {
            // 獲取當前線程
            final Thread current = Thread.currentThread();
            // 獲取鎖的狀態值
            int c = getState();
            if (c == 0) {//沒有線程正在競爭該鎖
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) { //等待線程隊列未空而且 state爲0且將state設置爲acquires的值 成功
                    // 設置當前線程獨佔
                    setExclusiveOwnerThread(current);
                    return true;//成功
                }
            }
            else if (current == getExclusiveOwnerThread()) {// 當前線程擁有該鎖
                int nextc = c + acquires;// 增長重入次數
                if (nextc < 0) // overflow(計數值小於0,則拋出異常)
                    throw new Error("Maximum lock count exceeded");
                // 設置狀態
                setState(nextc);
                return true;//成功
            }
            return false;//失敗
        }
    }

    //默認非公平策略
    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);//直接調用AbstractQueuedSynchronizer的方法
    }

    //僅在調用時鎖未被另外一個線程保持的狀況下,才獲取該鎖
    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);//非公平獲取鎖
    }

    //若是鎖在給定等待時間內沒有被另外一個線程保持,且當前線程未被中斷,則獲取該鎖
    public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));//直接調用AbstractQueuedSynchronizer的方法
    }

    //試圖釋放此鎖
    public void unlock() {
        sync.release(1);//直接調用AbstractQueuedSynchronizer的方法
    }

    //新增一個條件隊列
    public Condition newCondition() {
        return sync.newCondition();//調用sync的方法
    }

   //查詢當前線程保持此鎖的次數
    public int getHoldCount() {
        return sync.getHoldCount();//調用sync的方法
    }

    //查詢當前線程是否保持此鎖
    public boolean isHeldByCurrentThread() {
        return sync.isHeldExclusively();//調用sync的方法
    }

    //查詢此鎖是否由某一線程保持着
    public boolean isLocked() {
        return sync.isLocked();//調用sync的方法
    }

    //查詢當前對象是否爲公平鎖對象實例
    public final boolean isFair() {
        return sync instanceof FairSync;
    }

	//獲得鎖的當前持有線程對象
    protected Thread getOwner() {
        return sync.getOwner();
    }

    //查詢是否存在線程正在等待獲取此鎖
    public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();//調用AbstractQueuedSynchronizer的方法
    }

    //查詢某一線程是否正在等待獲取此鎖
    public final boolean hasQueuedThread(Thread thread) {
        return sync.isQueued(thread);//調用AbstractQueuedSynchronizer的方法
    }

    //返回正等待獲取此鎖的線程估計數
    public final int getQueueLength() {
        return sync.getQueueLength();//調用AbstractQueuedSynchronizer的方法
    }

    //返回一個collection,它包含可能正等待獲取此鎖的線程
    protected Collection<Thread> getQueuedThreads() {
        return sync.getQueuedThreads();//調用AbstractQueuedSynchronizer的方法
    }

   //查詢是否存在線程正在等待與此鎖有關的給定條件
    public boolean hasWaiters(Condition condition) {
        if (condition == null)//條件對象爲null,拋出空指針異常錯誤
            throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))//判斷對象類型
            throw new IllegalArgumentException("not owner");
        return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);//調用AbstractQueuedSynchronizer的方法
    }

    //返回等待與此鎖相關的給定條件的相關線程的估計數
    public int getWaitQueueLength(Condition condition) {
        if (condition == null)//條件對象爲null,拋出空指針異常錯誤
            throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))//判斷對象類型
            throw new IllegalArgumentException("not owner");
        return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);//調用AbstractQueuedSynchronizer的方法
    }

    //返回一個collection,它包含可能正在等待與此鎖相關給定條件的那些線程
    protected Collection<Thread> getWaitingThreads(Condition condition) {
        if (condition == null)//條件對象爲null,拋出空指針異常錯誤
            throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))//判斷對象類型
            throw new IllegalArgumentException("not owner");
        return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);//調用AbstractQueuedSynchronizer的方法
    }

    //返回標識此鎖及其鎖定狀態的字符串
    public String toString() {
        Thread o = sync.getOwner();//獲得持有鎖的線程實例
        return super.toString() + ((o == null) ?
                                   "[Unlocked]" :
                                   "[Locked by thread " + o.getName() + "]");
    }
}

類 ReentrantLock

public class ReentrantLock extends Object implements Lock, Serializable
已實現的接口:
    SerializableLockjava

 

    一個可重入的互斥鎖 Lock,它具備與使用 synchronized 方法和語句所訪問的隱式監視器鎖相同的一些基本行爲和語義,但功能更強大。api

    此類的構造方法接受一個可選的 公平 參數。數據結構

  • 當設置爲 true 時,在多個線程的爭用下,線程將按照它們發出請求的順序來得到鎖。
  • 當設置爲 false 時,只要線程在新發出請求的同時,該鎖狀態變爲可用,那麼線程將跳過隊列中其餘的等待線程並得到這個鎖。

    在公平的鎖中,若是有其餘線程持有這個鎖或者有其餘線程在隊列中等待這個鎖,那麼新發出請求的線程將被放入隊列中;在不公平的鎖中,只有當鎖被其餘的線程持有時,新發出請求的線程纔會被放入隊列中。多線程

    與採用默認設置(使用不公平鎖)相比,使用公平鎖的程序,因爲維護公平性而在掛起線程和恢復線程上增長了額外的開銷,從而在許多線程訪問時表現爲很低的整體吞吐量(即速度很慢,經常極其慢),可是在得到鎖和保證鎖分配的均衡性時差別較小。在大多數狀況下,非公平鎖的性能要高於公平鎖。ide

    須要注意的是,未定時的 tryLock 方法並無使用公平設置。所以即便其餘線程正在等待,只要該鎖是可用的,此方法就能夠得到成功。性能

 

    最典型的調用代碼以下:測試

 class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() { 
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }

    該類的序列化與內置鎖的行爲方式相同:一個反序列化的鎖處於解除鎖定狀態,無論它被序列化時的狀態是怎樣的。ui

    此鎖最多支持同一個線程發起的 2147483648 個遞歸鎖。試圖超過此限制會致使由鎖方法拋出的 Errorspa

 

構造方法摘要

ReentrantLock() 
          建立一個 ReentrantLock 的實例。
ReentrantLock(boolean fair) 
          建立一個具備給定公平策略的 ReentrantLock

 
    ReentrantLock總共有三個內部類,而且三個內部類是緊密相關的,下面先看三個類的關係。

  說明:ReentrantLock類內部總共存在Sync、NonfairSync、FairSync三個類,NonfairSync與FairSync類繼承自Sync類,Sync類繼承自AbstractQueuedSynchronizer抽象類。
        NonfairSync:每一次都嘗試獲取鎖,而並不會按照公平等待的原則進行等待,讓等待時間最久的線程得到鎖。
        FairSync:當資源空閒時,它老是會先判斷sync隊列(AbstractQueuedSynchronizer中的數據結構)是否有等待時間更長的線程,若是存在,則將該線程加入到等待隊列的尾部,實現了公平獲取原則。
  能夠看出 FairSync 只要資源被其餘線程佔用,該線程就會添加到sync queue中的尾部,而不會先嚐試獲取資源。這也是和 Nonfair 最大的區別,Nonfair 每一次都會嘗試去獲取資源,若是此時該資源剛好被釋放,則會被當前線程獲取,這就形成了不公平的現象,當獲取不成功,再加入隊列尾部。
 

方法摘要

 int getHoldCount() 
          查詢當前線程保持此鎖的次數。
protected  Thread getOwner() 
          返回目前擁有此鎖的線程,若是此鎖不被任何線程擁有,則返回 null
protected  Collection<Thread> getQueuedThreads() 
          返回一個 collection,它包含可能正等待獲取此鎖的線程。
 int getQueueLength() 
          返回正等待獲取此鎖的線程估計數。
protected  Collection<Thread> getWaitingThreads(Condition condition) 
          返回一個 collection,它包含可能正在等待與此鎖相關給定條件的那些線程。
 int getWaitQueueLength(Condition condition) 
          返回等待與此鎖相關的給定條件的線程估計數。
 boolean hasQueuedThread(Thread thread) 
          查詢給定線程是否正在等待獲取此鎖。
 boolean hasQueuedThreads() 
          查詢是否有些線程正在等待獲取此鎖。
 boolean hasWaiters(Condition condition) 
          查詢是否有些線程正在等待與此鎖有關的給定條件。
 boolean isFair() 
          若是此鎖的公平設置爲 true,則返回 true
 boolean isHeldByCurrentThread() 
          查詢當前線程是否保持此鎖。
 boolean isLocked() 
          查詢此鎖是否由任意線程保持。
 void lock() 
          獲取鎖。
 void lockInterruptibly() 
          若是當前線程未被中斷,則獲取鎖。
 Condition newCondition() 
          返回用來與此 Lock 實例一塊兒使用的 Condition 實例。
 String toString() 
          返回標識此鎖及其鎖定狀態的字符串。
 boolean tryLock() 
          僅在調用時鎖未被另外一個線程保持的狀況下,才獲取該鎖。
 boolean tryLock(long timeout, TimeUnit unit) 
          若是鎖在給定等待時間內沒有被另外一個線程保持,且當前線程未被中斷,則獲取該鎖。
 void unlock() 
          試圖釋放此鎖。

從類 java.lang.Object 繼承的方法:
    cloneequalsfinalizegetClasshashCodenotifynotifyAllwaitwaitwait

 

ReentrantLock

public ReentrantLock()

    建立一個 ReentrantLock 的實例。這等同於使用 ReentrantLock(false)
 

ReentrantLock

public ReentrantLock(boolean fair)

    建立一個具備給定公平策略的 ReentrantLock
    參數:
    fair - 若是此鎖應該使用公平的排序策略,則該參數爲 true
 

lock

public void lock()

    獲取鎖。
    若是該鎖沒有被另外一個線程保持,則獲取該鎖並當即返回,將鎖的保持計數設置爲 1。
    若是當前線程已經保持該鎖,則將保持計數加 1,而且該方法當即返回。
    若是該鎖被另外一個線程保持,則出於線程調度的目的,禁用當前線程,而且在得到鎖以前,該線程將一直處於休眠狀態,此時鎖保持計數被設置爲 1。
 

lockInterruptibly

public void lockInterruptibly() throws InterruptedException

    若是當前線程未被 中斷,則獲取鎖。
    若是該鎖沒有被另外一個線程保持,則獲取該鎖並當即返回,將鎖的保持計數設置爲 1。
    若是當前線程已經保持此鎖,則將保持計數加 1,而且該方法當即返回。
    若是鎖被另外一個線程保持,則出於線程調度目的,禁用當前線程,而且在發生如下兩種狀況之一之前,該線程將一直處於休眠狀態:

  • 鎖由當前線程得到;或者
  • 其餘某個線程中斷當前線程。

    若是當前線程得到該鎖,則將鎖保持計數設置爲 1。
    若是當前線程:

  • 在進入此方法時已經設置了該線程的中斷狀態;或者
  • 在等待獲取鎖的同時被中斷

    則拋出 InterruptedException,而且清除當前線程的已中斷狀態。
    在此實現中,由於此方法是一個顯式中斷點,因此要優先考慮響應中斷,而不是響應鎖的普通獲取或重入獲取。
    拋出:
   InterruptedException - 若是當前線程已中斷。
 

tryLock

public boolean tryLock()

    僅在調用時鎖未被另外一個線程保持的狀況下,才獲取該鎖。
    若是該鎖沒有被另外一個線程保持,而且當即返回 true 值,則將鎖的保持計數設置爲 1。即便已將此鎖設置爲使用公平排序策略,可是調用 tryLock() 仍 當即獲取鎖(若是有可用的),而無論其餘線程當前是否正在等待該鎖。在某些狀況下,此「闖入」行爲可能頗有用,即便它會打破公平性也如此。若是但願遵照此鎖的公平設置,則使用 tryLock(0, TimeUnit.SECONDS) ,它幾乎是等效的(也檢測中斷)。
    若是當前線程已經保持此鎖,則將保持計數加 1,該方法將返回 true
    若是鎖被另外一個線程保持,則此方法將當即返回 false 值。
    返回:
        若是鎖是自由的而且被當前線程獲取,或者當前線程已經保持該鎖,則返回 true;不然返回 false
 

tryLock

public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException

    若是鎖在給定等待時間內沒有被另外一個線程保持,且當前線程未被 中斷,則獲取該鎖。
    若是該鎖沒有被另外一個線程保持,而且當即返回 true 值,則將鎖的保持計數設置爲 1。若是爲了使用公平的排序策略,已經設置此鎖,而且其餘線程都在等待該鎖,則不會 獲取一個可用的鎖。這與 tryLock() 方法相反。若是想使用一個容許闖入公平鎖的定時 tryLock,那麼能夠將定時形式和不定時形式組合在一塊兒:

if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }

    若是當前線程已經保持此鎖,則將保持計數加 1,該方法將返回 true
    若是鎖被另外一個線程保持,則出於線程調度目的,禁用當前線程,而且在發生如下三種狀況之一之前,該線程將一直處於休眠狀態:

  • 鎖由當前線程得到;或者
  • 其餘某個線程中斷 當前線程;或者
  • 已超過指定的等待時間

    若是得到該鎖,則返回 true 值,並將鎖保持計數設置爲 1。
    若是當前線程:

  • 在進入此方法時已經設置了該線程的中斷狀態;或者
  • 在等待獲取鎖的同時被中斷

    則拋出 InterruptedException,而且清除當前線程的已中斷狀態。
    若是超出了指定的等待時間,則返回值爲 false。若是該時間小於等於 0,則此方法根本不會等待。
    在此實現中,由於此方法是一個顯式中斷點,因此要優先考慮響應中斷,而不是響應鎖的普通獲取或重入獲取,或者報告所用的等待時間。
    參數:
    timeout - 等待鎖的時間
    unit - timeout 參數的時間單位
    返回:
        若是鎖是自由的而且由當前線程獲取,或者當前線程已經保持該鎖,則返回 true;若是在獲取該鎖以前已經到達等待時間,則返回 false
    拋出:
    InterruptedException - 若是當前線程被中斷
    NullPointerException - 若是時間單位爲 null
 

unlock

public void unlock()

    試圖釋放此鎖。
    若是當前線程是此鎖全部者,則將保持計數減 1。若是保持計數如今爲 0,則釋放該鎖。若是當前線程不是此鎖的持有者,則拋出 IllegalMonitorStateException
    拋出:
    IllegalMonitorStateException - 若是當前線程沒有保持此鎖
 

newCondition

public Condition newCondition()

    返回用來與此 Lock 實例一塊兒使用的 Condition 實例。
    在使用內置監視器鎖時,返回的 Condition 實例支持與 Object 的監視器方法(waitnotify 和 notifyAll)相同的用法。

  • 在調用 Conditionwaiting 或 signalling 這些方法中的任意一個方法時,若是沒有保持此鎖,則將拋出 IllegalMonitorStateException
  • 在調用 waiting 條件方法時,將釋放鎖,並在這些方法返回以前,從新獲取該鎖,將鎖保持計數恢復爲調用方法時所持有的值。
  • 若是線程在等待時被中斷,則等待將終止,並將拋出 InterruptedException,清除線程的中斷狀態。
  • 等待線程按 FIFO 順序收到信號。
  • 等待方法返回的線程從新獲取鎖的順序與線程最初獲取鎖的順序相同,在默認狀況下,未指定此順序,但對於公平 鎖,它們更傾向於那些等待時間最長的線程。

    返回:
        Condition 對象
 

 

getHoldCount

public int getHoldCount()

    查詢當前線程保持此鎖的次數。
    對於與解除鎖操做不匹配的每一個鎖操做,線程都會保持一個鎖。
    保持計數信息一般只用於測試和調試。例如,若是不該該使用已經保持的鎖進入代碼的某一部分,則能夠聲明以下:

class X {
   ReentrantLock lock = new ReentrantLock();
   // ...     
   public void m() { 
     assert lock.getHoldCount() == 0;
     lock.lock();
     try {
       // ... method body
     } finally {
       lock.unlock();
     }
   }
 }

    返回:
        當前線程保持此鎖的次數,若是此鎖未被當前線程保持過,則返回 0
 

 

isHeldByCurrentThread

public boolean isHeldByCurrentThread()

    查詢當前線程是否保持此鎖。
    與內置監視器鎖的 Thread.holdsLock(java.lang.Object) 方法相似,此方法一般用於調試和測試。例如,只在保持某個鎖時才應調用的方法能夠聲明以下:

class X {
   ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() { 
       assert lock.isHeldByCurrentThread();
       // ... method body
   }
 }

    還能夠用此方法來確保某個重入鎖是否以非重入方式使用的,例如:

class X {
   ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() { 
       assert !lock.isHeldByCurrentThread();
       lock.lock();
       try {
           // ... method body
       } finally {
           lock.unlock();
       }
   }
 }

    返回:
        若是當前線程保持此鎖,則返回 true;不然返回 false
 

isLocked

public boolean isLocked()

    查詢此鎖是否由任意線程保持。此方法用於監視系統狀態,不用於同步控制。
    返回:
        若是任意線程保持此鎖,則返回 true;不然返回 false
 

isFair

public final boolean isFair()

    若是此鎖的公平設置爲 true,則返回 true
    返回:
        若是此鎖的公平設置爲 true,則返回 true
 

getOwner

protected Thread getOwner()

    返回目前擁有此鎖的線程,若是此鎖不被任何線程擁有,則返回 null。當此方法被不是擁有者的線程調用,返回值反映當前鎖狀態的最大近似值。 例如,擁有者能夠暫時爲 null,也就是說有些線程試圖獲取該鎖,但尚未實現。此方法用於加快子類的構造速度,提供更多的鎖監視設施。
    返回:
        擁有者,若是沒有,則返回 null
 

hasQueuedThreads

public final boolean hasQueuedThreads()

    查詢是否有些線程正在等待獲取此鎖。注意,由於隨時可能發生取消,因此返回 true 並不保證有其餘線程將獲取此鎖。此方法主要用於監視系統狀態。
    返回:
        若是可能有其餘線程正在等待獲取鎖,則返回 true
 

hasQueuedThread

public final boolean hasQueuedThread(Thread thread)

    查詢給定線程是否正在等待獲取此鎖。注意,由於隨時可能發生取消,因此返回 true 並不保證此線程將獲取此鎖。此方法主要用於監視系統狀態。
    參數:
    thread - 線程
    返回:
        若是給定線程已加入隊列而且正在等待此鎖,則返回 true
    拋出:
    NullPointerException - 若是 thread 爲 null
 

getQueueLength

public final int getQueueLength()

    返回正等待獲取此鎖的線程估計數。該值僅是估計的數字,由於在此方法遍歷內部數據結構的同時,線程的數目可能動態地變化。此方法用於監視系統狀態,不用於同步控制。
    返回:
        正在等待此鎖的線程估計數
 

getQueuedThreads

protected Collection<Thread> getQueuedThreads()

    返回一個 collection,它包含可能正等待獲取此鎖的線程。由於在構造此結果的同時實際的線程 set 可能動態地變化,因此返回的 collection 僅是盡力的估計值。所返回 collection 中的元素沒有特定的順序。此方法用於加快子類的構造速度,以提供更多的監視設施。
    返回:
        線程的 collection
 

hasWaiters

public boolean hasWaiters(Condition condition)

    查詢是否有些線程正在等待與此鎖有關的給定條件。注意,由於隨時可能發生超時和中斷,因此返回 true 並不保證未來某個 signal 將喚醒線程。此方法主要用於監視系統狀態。
    參數:
    condition - 條件
    返回:
        若是有任何等待的線程,則返回 true
    拋出:
    IllegalMonitorStateException - 若是沒有保持此鎖
    IllegalArgumentException - 若是給定 condition 與此鎖無關
    NullPointerException - 若是 condition 爲 null
 

getWaitQueueLength

public int getWaitQueueLength(Condition condition)

    返回等待與此鎖相關的給定條件的線程估計數。注意,由於隨時可能發生超時和中斷,因此只能將估計值做爲實際等待線程數的上邊界。此方法用於監視系統狀態,不用於同步控制。
    參數:
    condition - 條件
    返回:
        等待線程的估計數
    拋出:
    IllegalMonitorStateException - 若是沒有保持此鎖
    IllegalArgumentException - 若是給定 condition 與此鎖無關
    NullPointerException - 若是 condition 爲 null
 

getWaitingThreads

protected Collection<Thread> getWaitingThreads(Condition condition)

    返回一個 collection,它包含可能正在等待與此鎖相關給定條件的那些線程。由於在構造此結果的同時實際的線程 set 可能動態地變化,因此返回 collection 的元素只是盡力的估計值。所返回 collection 中的元素沒有特定的順序。此方法用於加快子類的構造速度,提供更多的條件監視設施。
    參數:
    condition - 條件
    返回:
        線程的 collection
    拋出:
    IllegalMonitorStateException - 若是沒有保持此鎖
    IllegalArgumentException - 若是給定 condition 與此鎖無關
    NullPointerException - 若是 condition 爲 null
 

toString

public String toString()

    返回標識此鎖及其鎖定狀態的字符串。該狀態括在括號中,它包括字符串 "Unlocked" 或字符串 "Locked by",後跟擁有線程的 名稱
    覆蓋:
        類 Object 中的 toString
    返回:
        標識此鎖及其鎖定狀態的字符串。
 

公平鎖和非公平鎖使用示例:

    注意:若是線程持有鎖的時間過長,則當全部線程都發送獲取的請求完畢,則沒法體現出公平鎖和非公平鎖的差別(發送請求的線程且剛好鎖也未被其餘線程所持有,公平鎖優先考慮等待隊列的第一個線程,非公平鎖則不考慮

    公平鎖:

package com.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class FairSyncDemo implements Runnable {
    Lock lock;

    FairSyncDemo(boolean isFair) {
        lock = new ReentrantLock(isFair);
    }

    @Override
    public void run() {
        System.out.println("我是線程:" + Thread.currentThread().getName());
        lock.lock();
        try {
            System.out.println("線程:" + Thread.currentThread().getName() + "獲取到鎖..");
        } finally {
            System.out.println("線程:" + Thread.currentThread().getName() + "即將釋放鎖..");
            System.out.println("------------------------");
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        FairSyncDemo fairSyncDemo = new FairSyncDemo(true);
        for (int i = 1; i <= 20; i++) {
            new Thread(fairSyncDemo).start();
        }
    }
}

    運行結果:

我是線程:Thread-0
我是線程:Thread-4
線程:Thread-0獲取到鎖..
線程:Thread-0即將釋放鎖..
------------------------
我是線程:Thread-3
我是線程:Thread-2
我是線程:Thread-1
我是線程:Thread-7
我是線程:Thread-6
我是線程:Thread-5
我是線程:Thread-9
我是線程:Thread-8
線程:Thread-4獲取到鎖..
線程:Thread-4即將釋放鎖..
------------------------
線程:Thread-3獲取到鎖..
線程:Thread-3即將釋放鎖..
------------------------
線程:Thread-2獲取到鎖..
線程:Thread-2即將釋放鎖..
------------------------
線程:Thread-1獲取到鎖..
線程:Thread-1即將釋放鎖..
------------------------
線程:Thread-7獲取到鎖..
線程:Thread-7即將釋放鎖..
------------------------
線程:Thread-6獲取到鎖..
線程:Thread-6即將釋放鎖..
------------------------
線程:Thread-5獲取到鎖..
線程:Thread-5即將釋放鎖..
------------------------
線程:Thread-9獲取到鎖..
線程:Thread-9即將釋放鎖..
------------------------
線程:Thread-8獲取到鎖..
線程:Thread-8即將釋放鎖..
------------------------

    能夠發現,線程獲取鎖的順序於它們各自start的順序一致。並且只要上一個線程釋放了鎖,下一個線程才能獲取獲得鎖。

    不公平鎖:

package com.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class FairSyncDemo implements Runnable {
    Lock lock;

    FairSyncDemo(boolean isFair) {
        lock = new ReentrantLock(isFair);
    }

    @Override
    public void run() {
        System.out.println("我是線程:" + Thread.currentThread().getName());
        try {
            lock.lock();
            System.out.println("線程:" + Thread.currentThread().getName() + "獲取到鎖..");
        } finally {
            System.out.println("線程:" + Thread.currentThread().getName() + "即將釋放鎖..");
            System.out.println("------------------------");
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        FairSyncDemo fairSyncDemo = new FairSyncDemo(false);
        for (int i = 1; i <= 10; i++) {
            new Thread(fairSyncDemo).start();
        }
    }
}

    將main()方法,建立FairSyncDemo實例的構造方法參數改成 false.
    運行結果:

我是線程:Thread-0
我是線程:Thread-4
我是線程:Thread-3
我是線程:Thread-1
我是線程:Thread-6
我是線程:Thread-2
線程:Thread-0獲取到鎖..
線程:Thread-0即將釋放鎖..
------------------------
我是線程:Thread-5
線程:Thread-3獲取到鎖..
線程:Thread-3即將釋放鎖..
------------------------
線程:Thread-4獲取到鎖..
線程:Thread-4即將釋放鎖..
------------------------
線程:Thread-1獲取到鎖..
線程:Thread-1即將釋放鎖..
------------------------
我是線程:Thread-9
我是線程:Thread-8
我是線程:Thread-7
線程:Thread-6獲取到鎖..
線程:Thread-6即將釋放鎖..
------------------------
線程:Thread-2獲取到鎖..
線程:Thread-2即將釋放鎖..
------------------------
線程:Thread-5獲取到鎖..
線程:Thread-5即將釋放鎖..
------------------------
線程:Thread-9獲取到鎖..
線程:Thread-9即將釋放鎖..
------------------------
線程:Thread-8獲取到鎖..
線程:Thread-8即將釋放鎖..
------------------------
線程:Thread-7獲取到鎖..
線程:Thread-7即將釋放鎖..
------------------------

    須要注意,即便是建立的公平鎖,調用tryLock() 則一樣是不公平的。

package com.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class FairSyncDemo implements Runnable {
    Lock lock;

    FairSyncDemo(boolean isFair) {
        lock = new ReentrantLock(isFair);
    }

    @Override
    public void run() {
        System.out.println("我是線程:" + Thread.currentThread().getName());
        boolean flag = true;
        try {
            flag = lock.tryLock();
            System.out.println("線程:" + Thread.currentThread().getName() + "獲取到鎖..");
        } finally {
            System.out.println("線程:" + Thread.currentThread().getName() + "即將釋放鎖..");
            System.out.println("------------------------");
            if (flag)
                lock.unlock();
        }
    }

    public static void main(String[] args) {
        FairSyncDemo fairSyncDemo = new FairSyncDemo(true);
        for (int i = 1; i <= 10; i++) {
            new Thread(fairSyncDemo).start();
        }
    }
}

    運行結果:

我是線程:Thread-0
我是線程:Thread-4
線程:Thread-4獲取到鎖..
我是線程:Thread-3
我是線程:Thread-1
我是線程:Thread-7
線程:Thread-3獲取到鎖..
線程:Thread-3即將釋放鎖..
------------------------
我是線程:Thread-6
線程:Thread-4即將釋放鎖..
------------------------
我是線程:Thread-2
線程:Thread-2獲取到鎖..
線程:Thread-2即將釋放鎖..
------------------------
線程:Thread-0獲取到鎖..
線程:Thread-0即將釋放鎖..
------------------------
我是線程:Thread-5
線程:Thread-6獲取到鎖..
線程:Thread-6即將釋放鎖..
------------------------
線程:Thread-7獲取到鎖..
線程:Thread-7即將釋放鎖..
------------------------
我是線程:Thread-9
線程:Thread-9獲取到鎖..
線程:Thread-9即將釋放鎖..
------------------------
我是線程:Thread-8
線程:Thread-8獲取到鎖..
線程:Thread-8即將釋放鎖..
------------------------
線程:Thread-1獲取到鎖..
線程:Thread-5獲取到鎖.. 線程:Thread-5即將釋放鎖.. ------------------------ 線程:Thread-1即將釋放鎖.. ------------------------
相關文章
相關標籤/搜索