ArrayList源碼分析--jdk1.8
LinkedList源碼分析--jdk1.8
HashMap源碼分析--jdk1.8
AQS源碼分析--jdk1.8
ReentrantLock源碼分析--jdk1.8java
1. ReentrantLock是獨佔鎖。
2. ReentrantLock分爲公平模式和非公平模式。
3. ReentrantLock鎖可重入(從新插入)node
/** * @since 1.5 * @author Doug Lea * 獨佔鎖 --默認使用非公平鎖模式 * 可重入 * * synchronized鎖經過監視器Monitor來實現同步,monitorenter加鎖,monitorexit解鎖。 * synchronized是可重如的非公平鎖 * synchronized在jdk1.6進行優化,添加了偏向鎖、輕量級鎖、重量級鎖,關鍵字之鎖的升級(偏向鎖->輕量級鎖->重量級鎖) * 偏向鎖:當線程訪問同步塊時,會使用 CAS 將線程 ID 更新到鎖對象的 Mark Word 中,若是更新成功則得到偏向鎖,而且以後每次進入這個對象鎖相關的同步塊時都不須要再次獲取鎖了。 * 輕量級鎖:若是同步對象爲無鎖狀態時,直接嘗試CAS更新Mark Word添加鎖,若是成功,得到鎖,失敗升級爲重量級鎖 * 重量級鎖:是指當鎖是輕量級鎖時,當自旋的線程自旋了必定的次數後,尚未獲取到鎖,就會進入阻塞狀態,該鎖升級爲重量級鎖,重量級鎖會使其餘線程阻塞,性能下降。 * 在使用 CAS 時,若是操做失敗,CAS 會自旋再次嘗試。因爲自旋是須要消耗 CPU 資源的,因此若是長期自旋就白白浪費了 CPU。JDK1.6加入了適應性自旋:若是某個鎖自旋不多成功得到,那麼下一次就會減小自旋。 */ public class ReentrantLock implements Lock, java.io.Serializable { private static final long serialVersionUID = 7373984872572414699L; private final Sync sync; /** * Sync內部類,繼承AQS,實現獨佔鎖模式,做爲基礎內部類 */ abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; /** * 加鎖 */ abstract void lock(); /** * 判斷 reentranLock 狀態 是否被鎖住(state ?= 0) * <p>若是沒被鎖住嘗試 原子性上鎖 失敗返回false</> * <p>若是被鎖住 判斷是不是當前線程持有鎖(重入鎖的實現) 若是是 state + 1 * (信號量 記錄該線程持有鎖的次數。 該線程每次釋放所 信號量 -1。 信號量爲零 表明 鎖被真正釋放)</> * <p>else 返回false</p> */ final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); //獲取到當前的線程 int c = getState(); //獲取鎖的狀態 if (c == 0) { //目前沒有人在佔有鎖 若是鎖已被經釋放 再次嘗試獲取鎖 if (compareAndSetState(0, acquires)) { //直接嘗試把當前只設置成1,若是成功,把owner設置本身,而且退出 setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { // 若是當前線程爲鎖的擁有者 int nextc = c + acquires; //這裏就是重入鎖的概念,若是仍是本身,則進行加1操做,由於釋放和獲取必定要是對等的 if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); // 累加 state 的值 此段代碼 實現了重入鎖 return true; } return false; //當前鎖被其餘線程佔用,退出。 } /** * 釋放鎖,默認releases傳1 */ protected final boolean tryRelease(int releases) { int c = getState() - releases; //獲取當前的鎖的狀態而且減1,由於要釋放鎖 if (Thread.currentThread() != getExclusiveOwnerThread()) //若是當前本身不是鎖的持有者,只有本身才能釋放鎖 throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { //釋放成功 free = true; setExclusiveOwnerThread(null); } setState(c); //從新設置成狀態 return free; } /** * 若是當前線程獨佔着鎖,返回true */ protected final boolean isHeldExclusively() { // While we must in general read state before owner, // we don't need to do so to check if current thread is owner return getExclusiveOwnerThread() == Thread.currentThread(); } /** * 條件隊列 */ final ConditionObject newCondition() { return new ConditionObject(); } /** * 返回鎖的擁有者的線程 * 當前狀態爲0返回null,說明在等待中 * 當前狀態不爲0返回當前線程 */ final Thread getOwner() { return getState() == 0 ? null : getExclusiveOwnerThread(); } /** * 當前線程佔着鎖返回 state,不然返回0 */ final int getHoldCount() { return isHeldExclusively() ? getState() : 0; } /** * state狀態不爲0標識上鎖,爲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 } } /** * 構造方法,默認選擇非公平鎖 */ public ReentrantLock() { sync = new NonfairSync(); } /** * 構造方法,true公平鎖,false非公平鎖 */ public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
ReentrantLock implements Lock
Sync extends AbstractQueuedSynchronizer
1.ReentrantLock實現Lock接口,Lock接口定義了加鎖、條件隊列、解鎖、加鎖(中斷異常)
2.Sync繼承AQS抽象類,實現了獨佔鎖,做爲基礎內部類lessReentrantLock源碼分析
1. FairSync公平鎖--內部類
/** * 公平鎖 */ static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; final void lock() { acquire(1); } /** * Fair version of tryAcquire. Don't grant access unless * recursive call or no waiters or is first. */ 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; } }
/** * 非公平鎖的同步對象 */ static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. * 非公平鎖,每次先去獲取對象,因此不排隊,不公平 */ final void lock() { // 經過原子操做 改變上鎖狀態 if (compareAndSetState(0, 1)) // 變動成功,說明獲取鎖成功 setExclusiveOwnerThread(Thread.currentThread()); // 設置持有者爲當前線程 else //變動失敗 acquire(1); //嘗試以獨佔模式獲取鎖,若是失敗加入node節點到隊列中 } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } /** * 是否有等待線程 */ public final boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } /** * 是否有等待線程 */ public final boolean hasQueuedThreads() { return head != tail; }
1)ReentrantLock是可重入的公平/非公平模式的獨佔鎖。 2)ReentrantLock公平鎖每每沒有非公平鎖的效率高,可是,並非任何場景都是以TPS做爲惟一指標,公平鎖 可以減小「飢餓」發生的機率,等待越久的請求越可以獲得優先知足。