ReentrantLock實現了lock接口,經過調用AbstractQueuedSynchronizer (AQS) 中的方法,實現了主要功能。html
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() + "]"); } }
public class ReentrantLock extends Object implements Lock, Serializable
已實現的接口:
Serializable, Lockjava
一個可重入的互斥鎖 Lock
,它具備與使用 synchronized
方法和語句所訪問的隱式監視器鎖相同的一些基本行爲和語義,但功能更強大。api
此類的構造方法接受一個可選的 公平 參數。數據結構
在公平的鎖中,若是有其餘線程持有這個鎖或者有其餘線程在隊列中等待這個鎖,那麼新發出請求的線程將被放入隊列中;在不公平的鎖中,只有當鎖被其餘的線程持有時,新發出請求的線程纔會被放入隊列中。多線程
與採用默認設置(使用不公平鎖)相比,使用公平鎖的程序,因爲維護公平性而在掛起線程和恢復線程上增長了額外的開銷,從而在許多線程訪問時表現爲很低的整體吞吐量(即速度很慢,經常極其慢),可是在得到鎖和保證鎖分配的均衡性時差別較小。在大多數狀況下,非公平鎖的性能要高於公平鎖。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 個遞歸鎖。試圖超過此限制會致使由鎖方法拋出的 Error
。spa
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 繼承的方法:
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
public ReentrantLock()
建立一個 ReentrantLock
的實例。這等同於使用 ReentrantLock(false)
。
public ReentrantLock(boolean fair)
建立一個具備給定公平策略的 ReentrantLock
。
參數:
fair
- 若是此鎖應該使用公平的排序策略,則該參數爲 true
public void lock()
獲取鎖。
若是該鎖沒有被另外一個線程保持,則獲取該鎖並當即返回,將鎖的保持計數設置爲 1。
若是當前線程已經保持該鎖,則將保持計數加 1,而且該方法當即返回。
若是該鎖被另外一個線程保持,則出於線程調度的目的,禁用當前線程,而且在得到鎖以前,該線程將一直處於休眠狀態,此時鎖保持計數被設置爲 1。
public void lockInterruptibly() throws InterruptedException
若是當前線程未被 中斷,則獲取鎖。
若是該鎖沒有被另外一個線程保持,則獲取該鎖並當即返回,將鎖的保持計數設置爲 1。
若是當前線程已經保持此鎖,則將保持計數加 1,而且該方法當即返回。
若是鎖被另外一個線程保持,則出於線程調度目的,禁用當前線程,而且在發生如下兩種狀況之一之前,該線程將一直處於休眠狀態:
若是當前線程得到該鎖,則將鎖保持計數設置爲 1。
若是當前線程:
則拋出 InterruptedException
,而且清除當前線程的已中斷狀態。
在此實現中,由於此方法是一個顯式中斷點,因此要優先考慮響應中斷,而不是響應鎖的普通獲取或重入獲取。
拋出:
InterruptedException
- 若是當前線程已中斷。
public boolean tryLock()
僅在調用時鎖未被另外一個線程保持的狀況下,才獲取該鎖。
若是該鎖沒有被另外一個線程保持,而且當即返回 true
值,則將鎖的保持計數設置爲 1。即便已將此鎖設置爲使用公平排序策略,可是調用 tryLock()
仍將 當即獲取鎖(若是有可用的),而無論其餘線程當前是否正在等待該鎖。在某些狀況下,此「闖入」行爲可能頗有用,即便它會打破公平性也如此。若是但願遵照此鎖的公平設置,則使用 tryLock(0, TimeUnit.SECONDS)
,它幾乎是等效的(也檢測中斷)。
若是當前線程已經保持此鎖,則將保持計數加 1,該方法將返回 true
。
若是鎖被另外一個線程保持,則此方法將當即返回 false
值。
返回:
若是鎖是自由的而且被當前線程獲取,或者當前線程已經保持該鎖,則返回 true
;不然返回 false
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
public void unlock()
試圖釋放此鎖。
若是當前線程是此鎖全部者,則將保持計數減 1。若是保持計數如今爲 0,則釋放該鎖。若是當前線程不是此鎖的持有者,則拋出 IllegalMonitorStateException
。
拋出:
IllegalMonitorStateException
- 若是當前線程沒有保持此鎖
public Condition newCondition()
返回用來與此 Lock
實例一塊兒使用的 Condition
實例。
在使用內置監視器鎖時,返回的 Condition
實例支持與 Object
的監視器方法(wait
、notify
和 notifyAll
)相同的用法。
Condition
、waiting 或 signalling 這些方法中的任意一個方法時,若是沒有保持此鎖,則將拋出 IllegalMonitorStateException
。InterruptedException
,清除線程的中斷狀態。 返回:
Condition 對象
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
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
public boolean isLocked()
查詢此鎖是否由任意線程保持。此方法用於監視系統狀態,不用於同步控制。
返回:
若是任意線程保持此鎖,則返回 true
;不然返回 false
public final boolean isFair()
若是此鎖的公平設置爲 true,則返回 true
。
返回:
若是此鎖的公平設置爲 true,則返回 true
protected Thread getOwner()
返回目前擁有此鎖的線程,若是此鎖不被任何線程擁有,則返回 null
。當此方法被不是擁有者的線程調用,返回值反映當前鎖狀態的最大近似值。 例如,擁有者能夠暫時爲 null
,也就是說有些線程試圖獲取該鎖,但尚未實現。此方法用於加快子類的構造速度,提供更多的鎖監視設施。
返回:
擁有者,若是沒有,則返回 null
public final boolean hasQueuedThreads()
查詢是否有些線程正在等待獲取此鎖。注意,由於隨時可能發生取消,因此返回 true
並不保證有其餘線程將獲取此鎖。此方法主要用於監視系統狀態。
返回:
若是可能有其餘線程正在等待獲取鎖,則返回 true
public final boolean hasQueuedThread(Thread thread)
查詢給定線程是否正在等待獲取此鎖。注意,由於隨時可能發生取消,因此返回 true
並不保證此線程將獲取此鎖。此方法主要用於監視系統狀態。
參數:
thread
- 線程
返回:
若是給定線程已加入隊列而且正在等待此鎖,則返回 true
拋出:
NullPointerException
- 若是 thread 爲 null
public final int getQueueLength()
返回正等待獲取此鎖的線程估計數。該值僅是估計的數字,由於在此方法遍歷內部數據結構的同時,線程的數目可能動態地變化。此方法用於監視系統狀態,不用於同步控制。
返回:
正在等待此鎖的線程估計數
protected Collection<Thread> getQueuedThreads()
返回一個 collection,它包含可能正等待獲取此鎖的線程。由於在構造此結果的同時實際的線程 set 可能動態地變化,因此返回的 collection 僅是盡力的估計值。所返回 collection 中的元素沒有特定的順序。此方法用於加快子類的構造速度,以提供更多的監視設施。
返回:
線程的 collection
public boolean hasWaiters(Condition condition)
查詢是否有些線程正在等待與此鎖有關的給定條件。注意,由於隨時可能發生超時和中斷,因此返回 true
並不保證未來某個 signal
將喚醒線程。此方法主要用於監視系統狀態。
參數:
condition
- 條件
返回:
若是有任何等待的線程,則返回 true
拋出:
IllegalMonitorStateException
- 若是沒有保持此鎖
IllegalArgumentException
- 若是給定 condition 與此鎖無關
NullPointerException
- 若是 condition 爲 null
public int getWaitQueueLength(Condition condition)
返回等待與此鎖相關的給定條件的線程估計數。注意,由於隨時可能發生超時和中斷,因此只能將估計值做爲實際等待線程數的上邊界。此方法用於監視系統狀態,不用於同步控制。
參數:
condition
- 條件
返回:
等待線程的估計數
拋出:
IllegalMonitorStateException
- 若是沒有保持此鎖
IllegalArgumentException
- 若是給定 condition 與此鎖無關
NullPointerException
- 若是 condition 爲 null
protected Collection<Thread> getWaitingThreads(Condition condition)
返回一個 collection,它包含可能正在等待與此鎖相關給定條件的那些線程。由於在構造此結果的同時實際的線程 set 可能動態地變化,因此返回 collection 的元素只是盡力的估計值。所返回 collection 中的元素沒有特定的順序。此方法用於加快子類的構造速度,提供更多的條件監視設施。
參數:
condition
- 條件
返回:
線程的 collection
拋出:
IllegalMonitorStateException
- 若是沒有保持此鎖
IllegalArgumentException
- 若是給定 condition 與此鎖無關
NullPointerException
- 若是 condition 爲 null
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即將釋放鎖.. ------------------------