* A reentrant mutual exclusion {@link Lock} with the same basic * behavior and semantics as the implicit monitor lock accessed using * {@code synchronized} methods and statements, but with extended * capabilities.
一個可重入的互斥鎖,它與使用synchronized的方法和語句來進行隱式鎖訪問的方式具備相同的基本行爲和語義,可是同時具備一些擴展功能。java
* <p>The constructor for this class accepts an optional * <em>fairness</em> parameter. When set {@code true}, under * contention, locks favor granting access to the longest-waiting * thread. Otherwise this lock does not guarantee any particular * access order. Programs using fair locks accessed by many threads * may display lower overall throughput (i.e., are slower; often much * slower) than those using the default setting, but have smaller * variances in times to obtain locks and guarantee lack of * starvation.
ReentrantLock構造方法接收一個可選的公平參數。當設置爲true時,它是公平鎖,這時鎖會將訪問權授予等待時間最長的線程。不然該鎖將沒法保證線程獲取鎖的訪問順序。公平鎖與非公平鎖相比,使用公平鎖的程序會有較低的吞吐量,但使用公平鎖能有效減小線程飢餓的發生。ui
使用建議:通常推薦的使用方式就是 lock()後緊跟try塊,例如:this
class X { private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock() } } }}
private final Sync sync; /** * Base of synchronization control for this lock. Subclassed * into fair and nonfair versions below. Uses AQS state to * represent the number of holds on the lock. */ abstract static class Sync extends AbstractQueuedSynchronizer /** * Sync object for non-fair locks */ static final class NonfairSync extends Sync /** * Sync object for fair locks */ static final class FairSync extends Sync
以上爲ReentrantLock提供的3個靜態內部類,其中Sync類繼承自AbstractQueuedSynchronizer(抽象隊列同步器),而NonfairSync和FairSync爲Sync類的兩個實現,分別應用於非公平鎖和公平鎖的場景,而公平鎖和非公平鎖在釋放鎖的狀況都是同樣的,只是在獲取鎖時,公平鎖會讓等待最久的線程優先獲取到鎖,而非公平鎖在獲取鎖時各線程機會均等,這樣也就致使會出現飢餓現象產生.線程
static final class FairSync extends Sync final void lock() {acquire(1);}
static final class NonfairSync extends Sync { final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } }
以上爲公平鎖和非公平鎖調用lock()的源碼,其中的compareAndSetState,setExclusiveOwnerThread和acquire 均來自AQS中,有次能夠看出非公平鎖在lock時就會去嘗試1次去獲取鎖,獲取到了就返回,若是獲取不到,則跟公平鎖同樣,調用acquire(arg)再次嘗試獲取鎖,說白了,非公平鎖比公平鎖多1次搶佔鎖的動做。而在搶佔動做中,非公平鎖是直接嘗試搶佔,而公平鎖會先判斷是否位於頭結點來決定是否搶佔。code
非公平鎖獲取鎖源碼繼承
final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
公平鎖獲取鎖源碼隊列
protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { 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; }
場景1 防止重複執行ci
ReentrantLock lock = new ReentrantLock(); if(lock.tryLock()){//若是已經被lock,則直接放回false,不會等待,達到忽略的效果 try { }finally { lock.unlock(); } }
場景2 串行執行(同步執行,相似synchronized)get
try { lock.lock(); }finally { lock.unlock(); }
場景3 超時等待同步
try{ if(lock.tryLock(5, TimeUnit.SECONDS)){ try { }finally { lock.unlock(); } } }catch (InterruptedException ex){ ex.printStackTrace(); }
場景4 響應中斷
try { lock.lockInterruptibly(); } catch (InterruptedException ex) { ex.printStackTrace(); } finally { lock.unlock(); }