J.U.C剖析與解讀2(AQS的由來)


J.U.C剖析與解讀2(AQS的由來)

前言

前面已經通過實現自定義ReentrantLock與自定義ReentrantReadWriteLock,展示了JDK是如何實現獨占鎖與共享鎖的。

那么實際JDK源碼中的ReentrantLock與ReentrantReadWritreLock是如何實現的呢?我們現有的自定義代碼是否可以更進一步呢?

答案是肯定的。注意看我之前兩個Lock的朋友,應該注意到了。自定義ReentrantReadWriteLock的獨占鎖部分,其實和自定義ReentrantLock是幾乎一樣的。

也就是說,不同Lock其實現是差不多的。那么是否可以提取公共的部分,是否可以寫得更加優雅一些。

那么這篇博客,就是通過提取公共代碼,引入模板方法設計模式,並利用Java的一些特性,寫出一個自定義的AQS。

當然,最后也會剖析源碼中AQS實現與我們自定義AQS的差別所在,並解讀源碼AQS中一些高級應用,如AQS通過一個state實現讀寫鎖的持有數量(居然通過一個int值的CAS操作,解決了自定義讀寫鎖持有數量的獨占操作)。

如果看過源碼的朋友,會發現源碼中的ReentrantLock會自定義一個Sync,該Sync會繼承一個AbstratQueueSynchronizer(簡稱AQS)。然后源碼中的ReentrantLock的tryLock等方法,則是調用Sync的對應子類(FairSync或NonFairSync,也就是是否為公平鎖)來實現對應功能。並且,只有tryAcquire與lock兩個方法是由ReentrantLock實現的,其它方法是由AQS提供的。lock是由FairSync與NonFairSync分別實現的。而tryAcquire是由FairSync與NonFairSync父類的Sync實現,NonFairSync的tryLock直接調用父類Sync的nonfairTryAcquire方法。

而ReentrantReadWriteLock則是增加了ReadLock與WriteLock,其實現,則是調用Sync的不同方法而已。

有的小伙伴,會覺得這樣的關系很復雜,明明一個鎖就比較復雜了,還搞得這么抽象。提取一個AQS就夠抽象的了,每個鎖還整了一個Sync,FairSync,NonFairSync內部類,視情況,還要弄個ReadLock,WriteLock這些內部類。這樣做的目的其實是為了封裝代碼,提高代碼復用性。當然,實際源碼看多了,反而會覺得這樣的代碼,看得挺舒服的。比較符合設計理念(想想,你接收的項目中,一個類上千行代碼,完全不敢修改)。

關於讀源碼,簡單說一下我的感受。最核心的就是堅持,最重要的是全局觀,最需要的是積累。

我陸陸續續閱讀源碼(不只是Java),也有差不多兩年的經驗吧。從最早的Windows內核源碼,到后面的前端框架源碼,到今年的Java源碼閱讀。最早的Windows內核源碼,那真的是無知者無畏啊,簡直是一段極其痛苦的經歷。那時候一天可能就二十頁樣子,還得看運氣。但是那段時間給我帶來了很多,包括什么系統內存管理,內存的用戶態與內核態,以及系統上下文等積累,為我后面的提升帶來了很多。而后面的前端源碼的閱讀,也讓我開始接觸源碼的一些思路。最后到今年的Java源碼,有了去年golang一些外文博客的翻譯(涉及語言設計部分)鋪墊,才漸漸有了一些閱讀源碼的感覺(自我感覺有點上路了)。所以,最核心的是堅持。

至於全局觀嘛,就是一方面很多時候源碼太多,常常迷路,我們需要把握主線,以及自己的目的。如果可以有一個XMIND,或者比較不錯的博客等作為指引就更好了。比如這次AQS拆分,我就是從網易雲的大佬James學到的。雖然之前就有了JUC學習的積累,但是大佬的AQS拆分,確實令我對AQS有了更為深入的理解。另一方面就是需要把握自己應該研究的深度(在自己能力層級再深入一些即可),而不是抓着源碼的每個字不放。我今年年初的時候,就想研究IOC源碼,根據一位大佬的文章,連續啃了兩三個星期。但后面陸陸續續就忘了。雖然這段經歷對我依舊有着一定的積累價值(對我最近研究SpringApplication的run過程有着不錯的價值),但是超出自己能力太多地擼源碼,性價比就太低了。

最后就是積累,我非常看重積累。自從高三后,我就對積累這個詞有了更深入的理解。很多時候,我們閱讀一些書籍,研究一些原理,雖然后來感覺忘記了,但是積累還是在的。就像我學習編程時,就經常感受到大學時期的計算機網絡,計算機原理,分布式課題等經歷給我帶來的積累。而現在很多人都過於看重即時價值(就是我立馬學了,立馬就要有效果),而我相信技術的攀登,是離不開經年累月的積累的。

如果大家對閱讀源碼,感興趣的話,可以告訴我。可以考慮寫一篇文章,來簡單談談源碼閱讀這件事兒。

一,簡易JUC(版本一):

這里就是將之前實現的簡易版ReentrantLock與ReentrantReadWriteLock展現出來,就當是簡單回顧一下。

1.JarryReentrantLock:


	package tech.jarry.learning.netease.locks2;
	
	import java.util.concurrent.LinkedBlockingQueue;
	import java.util.concurrent.TimeUnit;
	import java.util.concurrent.atomic.AtomicInteger;
	import java.util.concurrent.atomic.AtomicReference;
	import java.util.concurrent.locks.Condition;
	import java.util.concurrent.locks.Lock;
	import java.util.concurrent.locks.LockSupport;
	
	/**
	 * @Description: 仿ReentrantLock,實現其基本功能及特性
	 * @Author: jarry
	 */
	public class JarryReentrantLock {
	
		private AtomicInteger count = new AtomicInteger(0);
		private AtomicReference<Thread> owner = new AtomicReference<>();
		private LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>();
	
		public void lock() {
			int arg = 1;
			if (!tryLock(arg)){
				waiters.offer(Thread.currentThread());
				while (true){
					Thread head = waiters.peek();
					if (head == Thread.currentThread()){
						if (!tryLock(arg)){
							LockSupport.park();
						} else {
							waiters.poll();
							return;
						}
					} else {
						LockSupport.park();
					}
				}
			}
		}
	
		public void unlock() {
			int arg = 1;
			if (tryUnlock(arg)){
				Thread head = waiters.peek();
				if (head != null){
					LockSupport.unpark(head);
				}
			}
		}
	
		public boolean tryLock(int acquires) {
			int countValue = count.get();
			if (countValue != 0){
				if (Thread.currentThread() == owner.get()){
					count.set(countValue+acquires);
					return true;
				}else{
					return false;
				}
			}else {
				if (count.compareAndSet(countValue,countValue+acquires)){
					owner.set(Thread.currentThread());
					return true;
				} else {
					return false;
				}
			}
		}
	
		private boolean tryUnlock(int releases) {
			if (Thread.currentThread() != owner.get()){
				throw new IllegalMonitorStateException();
			} else {
				int countValue = count.get();
				int countNextValue = countValue - releases;
				count.compareAndSet(countValue,countNextValue);
				if (countNextValue == 0){
					owner.compareAndSet(Thread.currentThread(),null);
					return true;
				} else {
					return false;
				}
			}
		}
	
		public void lockInterruptibly() throws InterruptedException {
	
		}
	
		public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
			return false;
		}
	
		public Condition newCondition() {
			return null;
		}
	}

2.JarryReadWriteLock:


	package tech.jarry.learning.netease.locks2;
	
	import java.util.concurrent.LinkedBlockingQueue;
	import java.util.concurrent.atomic.AtomicInteger;
	import java.util.concurrent.atomic.AtomicReference;
	import java.util.concurrent.locks.LockSupport;
	
	/**
	 * @Description:
	 * @Author: jarry
	 */
	public class JarryReadWriteLock {
	
		volatile AtomicInteger readCount = new AtomicInteger(0);
		AtomicInteger writeCount = new AtomicInteger(0);
		AtomicReference<Thread> owner = new AtomicReference<>();
		public volatile LinkedBlockingQueue<WaitNode> waiters = new LinkedBlockingQueue<>();
	
		class WaitNode{
			Thread thread = null;
			// 表示希望爭取的鎖的類型。0表示寫鎖(獨占鎖),1表示讀鎖(共享鎖)
			int type = 0;
			int arg = 0;
	
			public WaitNode(Thread thread, int type, int arg) {
				this.type = type;
				this.thread = thread;
				this.arg = arg;
			}
		}
	
		/**
		 * 獲取獨占鎖(針對獨占鎖)
		 */
		public void lock(){
			int arg = 1;
			if (!tryLock(arg)){
				WaitNode waitNode = new WaitNode(Thread.currentThread(), 0, arg);
				waiters.offer(waitNode);
	
				while (true){
					WaitNode headNote = waiters.peek();
					if (headNote !=null && headNote.thread == Thread.currentThread()){
						if (!tryLock(headNote.arg)){
							LockSupport.park();
						} else {
							waiters.poll();
							return;
						}
					}else {
						LockSupport.park();
					}
				}
			}
		}
	
		/**
		 * 解鎖(針對獨占鎖)
		 */
		public void unlock(){
			int arg = 1;
			if (tryUnlock(arg)){
				WaitNode head = waiters.peek();
				if (head == null){
					return;
				}
				LockSupport.unpark(head.thread);
			}
		}
	
		/**
		 * 嘗試獲取獨占鎖(針對獨占鎖)
		 * @param acquires 用於加鎖次數。一般傳入waitNode.arg(本代碼中就是1。為什么不用一個常量1,就不知道了?)
		 * @return
		 */
		public boolean tryLock(int acquires){
			if (readCount.get() == 0){
				int writeCountValue = writeCount.get();
				if (writeCountValue == 0){
					if (writeCount.compareAndSet(writeCountValue,writeCountValue+acquires)){
						owner.set(Thread.currentThread());
						return true;
					}
				} else {
					if (Thread.currentThread() == owner.get()){
						writeCount.set(writeCountValue+acquires);
						return true;
					}
				}
			}
			return false;
		}
	
		/**
		 * 嘗試解鎖(針對獨占鎖)
		 * @param releases 用於設定解鎖次數。一般傳入waitNode.arg
		 * @return
		 */
		public boolean tryUnlock(int releases){
			if (owner.get() != Thread.currentThread()){
				throw new IllegalMonitorStateException();
			}
			int writeCountValue = writeCount.get();
			writeCount.set(writeCountValue-releases);
			if (writeCount.get() == 0){
				owner.compareAndSet(Thread.currentThread(),null);
				return true;
			} else {
				return false;
			}
		}
	
		/**
		 * 獲取共享鎖(針對共享鎖)
		 */
		public void lockShared(){
			int arg = 1;
			if (!tryLockShared(arg)){
				WaitNode waitNode = new WaitNode(Thread.currentThread(),1,arg);
				waiters.offer(waitNode);
	
				while (true){
					WaitNode head = waiters.peek();
					if (head != null && head.thread == Thread.currentThread()){
						if (tryLockShared(head.arg)){
							waiters.poll();
	
							WaitNode newHead = waiters.peek();
							if (newHead != null && newHead.type == 1){
								LockSupport.unpark(newHead.thread);
							}
							return;
						} else {
							LockSupport.park();
						}
					} else {
						LockSupport.park();
					}
				}
			}
		}
	
		/**
		 * 解鎖(針對共享鎖)
		 */
		public boolean unLockShared(){
			int arg = 1;
			if (tryUnLockShared(arg)){
				WaitNode head = waiters.peek();
				if (head != null){
					LockSupport.unpark(head.thread);
				}
				return true;
			}
			return false;
		}
	
		/**
		 * 嘗試獲取共享鎖(針對共享鎖)
		 * @param acquires
		 * @return
		 */
		public boolean tryLockShared(int acquires){
			while (true){
				if (writeCount.get() == 0 || owner.get() == Thread.currentThread()){
					int readCountValue = readCount.get();
					if (readCount.compareAndSet(readCountValue, readCountValue+acquires)){
						return true;
					}
				}
				return false;
			}
		}
	
		/**
		 * 嘗試解鎖(針對共享鎖)
		 * @param releases
		 * @return
		 */
		public boolean tryUnLockShared(int releases){
			while (true){
				int readCountValue = readCount.get();
				int readCountNext = readCountValue - releases;
				if (readCount.compareAndSet(readCountValue,readCountNext)){
					return readCountNext == 0;
				}
			}
		}
	
	}

二,簡易JUC(版本二):

很明顯,上面的代碼中,JarryReentrantLock的tryLock等方法與JarryReadWriteLock中共享鎖的tryLock等方法是類似的(本來就是從JarryReentrantLock復制過來的嘛)。那么,這里就需要引入模板方法(詳見筆記《設計模式》-模板方法)。通過一個commonMask類,來提取公共方法。

1.CommonMask:


	package tech.jarry.learning.netease.locks3;
	
	import java.util.concurrent.LinkedBlockingQueue;
	import java.util.concurrent.atomic.AtomicInteger;
	import java.util.concurrent.atomic.AtomicReference;
	import java.util.concurrent.locks.LockSupport;
	
	/**
	 * @Description:
	 * @Author: jarry
	 */
	public class CommonMask {
	
		volatile AtomicInteger readCount = new AtomicInteger(0);
		AtomicInteger writeCount = new AtomicInteger(0);
		AtomicReference<Thread> owner = new AtomicReference<>();
		public volatile LinkedBlockingQueue<WaitNode> waiters = new LinkedBlockingQueue<>();
	
		class WaitNode{
			Thread thread = null;
			// 表示希望爭取的鎖的類型。0表示寫鎖(獨占鎖),1表示讀鎖(共享鎖)
			int type = 0;
			int arg = 0;
	
			public WaitNode(Thread thread, int type, int arg) {
				this.type = type;
				this.thread = thread;
				this.arg = arg;
			}
		}
	
		/**
		 * 獲取獨占鎖(針對獨占鎖)
		 */
		public void lock(){
			int arg = 1;
			if (!tryLock(arg)){
				WaitNode waitNode = new WaitNode(Thread.currentThread(), 0, arg);
				waiters.offer(waitNode);
	
				while (true){
					WaitNode headNote = waiters.peek();
					if (headNote !=null && headNote.thread == Thread.currentThread()){
						if (!tryLock(headNote.arg)){
							LockSupport.park();
						} else {
							waiters.poll();
							return;
						}
					}else {
						LockSupport.park();
					}
				}
			}
		}
	
		/**
		 * 解鎖(針對獨占鎖)
		 */
		public void unlock(){
			int arg = 1;
			if (tryUnlock(arg)){
				WaitNode head = waiters.peek();
				if (head == null){
					return;
				}
				LockSupport.unpark(head.thread);
			}
		}
	
		/**
		 * 嘗試獲取獨占鎖(針對獨占鎖)
		 * @param acquires 用於加鎖次數。一般傳入waitNode.arg(本代碼中就是1。為什么不用一個常量1,就不知道了?)
		 * @return
		 */
		public boolean tryLock(int acquires){
			if (readCount.get() == 0){
				int writeCountValue = writeCount.get();
				if (writeCountValue == 0){
					if (writeCount.compareAndSet(writeCountValue,writeCountValue+acquires)){
						owner.set(Thread.currentThread());
						return true;
					}
				} else {
					if (Thread.currentThread() == owner.get()){
						writeCount.set(writeCountValue+acquires);
						return true;
					}
				}
			}
			return false;
		}
	
		/**
		 * 嘗試解鎖(針對獨占鎖)
		 * @param releases 用於設定解鎖次數。一般傳入waitNode.arg
		 * @return
		 */
		public boolean tryUnlock(int releases){
			if (owner.get() != Thread.currentThread()){
				throw new IllegalMonitorStateException();
			}
			int writeCountValue = writeCount.get();
			writeCount.set(writeCountValue-releases);
			if (writeCount.get() == 0){
				owner.compareAndSet(Thread.currentThread(),null);
				return true;
			} else {
				return false;
			}
		}
	
		/**
		 * 獲取共享鎖(針對共享鎖)
		 */
		public void lockShared(){
			int arg = 1;
			if (!tryLockShared(arg)){
				WaitNode waitNode = new WaitNode(Thread.currentThread(),1,arg);
				waiters.offer(waitNode);
	
				while (true){
					WaitNode head = waiters.peek();
					if (head != null && head.thread == Thread.currentThread()){
						if (tryLockShared(head.arg)){
							waiters.poll();
	
							WaitNode newHead = waiters.peek();
							if (newHead != null && newHead.type == 1){
								LockSupport.unpark(newHead.thread);
							}
							return;
						} else {
							LockSupport.park();
						}
					} else {
						LockSupport.park();
					}
				}
			}
		}
	
		/**
		 * 解鎖(針對共享鎖)
		 */
		public boolean unLockShared(){
			int arg = 1;
			if (tryUnLockShared(arg)){
				WaitNode head = waiters.peek();
				if (head != null){
					LockSupport.unpark(head.thread);
				}
				return true;
			}
			return false;
		}
	
		/**
		 * 嘗試獲取共享鎖(針對共享鎖)
		 * @param acquires
		 * @return
		 */
		public boolean tryLockShared(int acquires){
			while (true){
				if (writeCount.get() == 0 || owner.get() == Thread.currentThread()){
					int readCountValue = readCount.get();
					if (readCount.compareAndSet(readCountValue, readCountValue+acquires)){
						return true;
					}
				}
				return false;
			}
		}
	
		/**
		 * 嘗試解鎖(針對共享鎖)
		 * @param releases
		 * @return
		 */
		public boolean tryUnLockShared(int releases){
			while (true){
				int readCountValue = readCount.get();
				int readCountNext = readCountValue - releases;
				if (readCount.compareAndSet(readCountValue,readCountNext)){
					return readCountNext == 0;
				}
			}
		}
	}

2.JarryReentrantLock:


	package tech.jarry.learning.netease.locks3;
	
	import java.util.concurrent.LinkedBlockingQueue;
	import java.util.concurrent.TimeUnit;
	import java.util.concurrent.atomic.AtomicInteger;
	import java.util.concurrent.atomic.AtomicReference;
	import java.util.concurrent.locks.Condition;
	import java.util.concurrent.locks.Lock;
	import java.util.concurrent.locks.LockSupport;
	
	/**
	 * @Description: 仿ReentrantLock,實現其基本功能及特性
	 * @Author: jarry
	 */
	public class JarryReentrantLock {
	
		private CommonMask commonMask = new CommonMask();
	
		public void lock() {
			commonMask.lock();
		}
	
		public void unlock() {
			commonMask.unlock();
		}
	
		public boolean tryLock(int acquire) {
			return commonMask.tryLock(acquire);
		}
	
		private boolean tryUnlock(int release) {
			return commonMask.tryUnlock(release);
		}
	}

3.JarryReadWriteLock:


	package tech.jarry.learning.netease.locks3;
	
	import java.util.concurrent.LinkedBlockingQueue;
	import java.util.concurrent.atomic.AtomicInteger;
	import java.util.concurrent.atomic.AtomicReference;
	import java.util.concurrent.locks.LockSupport;
	
	/**
	 * @Description:
	 * @Author: jarry
	 */
	public class JarryReadWriteLock {
	
		private CommonMask commonMask = new CommonMask();
	
		/**
		 * 獲取獨占鎖(針對獨占鎖)
		 */
		public void lock(){
			commonMask.lock();
		}
	
		/**
		 * 解鎖(針對獨占鎖)
		 */
		public void unlock(){
			commonMask.unlock();
		}
	
		/**
		 * 嘗試獲取獨占鎖(針對獨占鎖)
		 * @param acquires 用於加鎖次數。一般傳入waitNode.arg(本代碼中就是1。為什么不用一個常量1,就不知道了?)
		 * @return
		 */
		public boolean tryLock(int acquires){
			return commonMask.tryLock(acquires);
		}
	
		/**
		 * 嘗試解鎖(針對獨占鎖)
		 * @param releases 用於設定解鎖次數。一般傳入waitNode.arg
		 * @return
		 */
		public boolean tryUnlock(int releases){
			return commonMask.tryUnlock(releases);
		}
	
		/**
		 * 獲取共享鎖(針對共享鎖)
		 */
		public void lockShared(){
			commonMask.lockShared();
		}
	
		/**
		 * 解鎖(針對共享鎖)
		 */
		public boolean unLockShared(){
			return commonMask.unLockShared();
		}
	
		/**
		 * 嘗試獲取共享鎖(針對共享鎖)
		 * @param acquires
		 * @return
		 */
		public boolean tryLockShared(int acquires){
			return tryLockShared(acquires);
		}
	
		/**
		 * 嘗試解鎖(針對共享鎖)
		 * @param releases
		 * @return
		 */
		public boolean tryUnLockShared(int releases){
			return commonMask.tryUnLockShared(releases);
		}
	
	}

到了這里,大家就可以明顯看出,總體代碼量的下降(這還只是兩個Lock)。但是問題也出來了,那就是這樣將所有方法都放在父類CommonMask,子類進行調用,是不是顯得過於死板(說得直接點,就是這種操作,完全就是將代碼往父類一拋而已)。這說明,之前代碼公共提取做得並不好。

重新整理思路,JarryReentrantLock與JarryReadWriteLock的共同之處到底在哪里。細想一下,發現這兩個方法的lock,unlock等操作是一致的,只是實際的運行邏輯方法tryLock,tryUnlock,tryLockShared,tryUnLockShared四個方法(在框架源碼中,常常用doxxx方法,表示實際運行邏輯的方法)。所以CommonMask應該實現的是這四個方法之外的方法,而這四個方法交由子類,來根據具體需要來實現(CommonMask中,這四個方法直接拋出對應異常)。

最后,ReentrantLock是有公平鎖,非公平鎖之分的。而通過上面的調整,現在的JarryReentrantLock可以實現自己對應方法,來展現特性(公平鎖/非公平鎖的選擇)了。

三,簡易JUC(版本三):

1.CommonMask:


	package tech.jarry.learning.netease.locks4;
	
	import java.util.concurrent.LinkedBlockingQueue;
	import java.util.concurrent.atomic.AtomicInteger;
	import java.util.concurrent.atomic.AtomicReference;
	import java.util.concurrent.locks.LockSupport;
	
	/**
	 * @Description:
	 * @Author: jarry
	 */
	public class CommonMask {
	
		volatile AtomicInteger readCount = new AtomicInteger(0);
		AtomicInteger writeCount = new AtomicInteger(0);
		AtomicReference<Thread> owner = new AtomicReference<>();
		public volatile LinkedBlockingQueue<WaitNode> waiters = new LinkedBlockingQueue<>();
	
		class WaitNode{
			Thread thread = null;
			// 表示希望爭取的鎖的類型。0表示寫鎖(獨占鎖),1表示讀鎖(共享鎖)
			int type = 0;
			int arg = 0;
	
			public WaitNode(Thread thread, int type, int arg) {
				this.type = type;
				this.thread = thread;
				this.arg = arg;
			}
		}
	
		/**
		 * 獲取獨占鎖(針對獨占鎖)
		 */
		public void lock(){
			int arg = 1;
			if (!tryLock(arg)){
				WaitNode waitNode = new WaitNode(Thread.currentThread(), 0, arg);
				waiters.offer(waitNode);
	
				while (true){
					WaitNode headNote = waiters.peek();
					if (headNote !=null && headNote.thread == Thread.currentThread()){
						if (!tryLock(headNote.arg)){
							LockSupport.park();
						} else {
							waiters.poll();
							return;
						}
					}else {
						LockSupport.park();
					}
				}
			}
		}
	
		/**
		 * 解鎖(針對獨占鎖)
		 */
		public void unlock(){
			int arg = 1;
			if (tryUnlock(arg)){
				WaitNode head = waiters.peek();
				if (head == null){
					return;
				}
				LockSupport.unpark(head.thread);
			}
		}
	
	
		/**
		 * 獲取共享鎖(針對共享鎖)
		 */
		public void lockShared(){
			int arg = 1;
			if (!tryLockShared(arg)){
				WaitNode waitNode = new WaitNode(Thread.currentThread(),1,arg);
				waiters.offer(waitNode);
	
				while (true){
					WaitNode head = waiters.peek();
					if (head != null && head.thread == Thread.currentThread()){
						if (tryLockShared(head.arg)){
							waiters.poll();
	
							WaitNode newHead = waiters.peek();
							if (newHead != null && newHead.type == 1){
								LockSupport.unpark(newHead.thread);
							}
							return;
						} else {
							LockSupport.park();
						}
					} else {
						LockSupport.park();
					}
				}
			}
		}
	
		/**
		 * 解鎖(針對共享鎖)
		 */
		public boolean unLockShared(){
			int arg = 1;
			if (tryUnLockShared(arg)){
				WaitNode head = waiters.peek();
				if (head != null){
					LockSupport.unpark(head.thread);
				}
				return true;
			}
			return false;
		}
	
		/**
		 * 嘗試獲取獨占鎖(針對獨占鎖)
		 * @param acquires
		 * @return
		 */
		public boolean tryLock(int acquires){
			throw new UnsupportedOperationException();
		}
	
		/**
		 * 嘗試解鎖(針對獨占鎖)
		 * @param releases 用於設定解鎖次數。一般傳入waitNode.arg
		 * @return
		 */
		public boolean tryUnlock(int releases){
			throw new UnsupportedOperationException();
		}
	
		/**
		 * 嘗試獲取共享鎖(針對共享鎖)
		 * @param acquires
		 * @return
		 */
		public boolean tryLockShared(int acquires){
			throw new UnsupportedOperationException();
		}
	
		/**
		 * 嘗試解鎖(針對共享鎖)
		 * @param releases
		 * @return
		 */
		public boolean tryUnLockShared(int releases){
			throw new UnsupportedOperationException();
		}
	}

2.JarryReentrantLock:


	package tech.jarry.learning.netease.locks4;
	
	/**
	 * @Description: 仿ReentrantLock,實現其基本功能及特性
	 * @Author: jarry
	 */
	public class JarryReentrantLock {
	
		private boolean isFair;
	
		// 默認采用非公平鎖,保證效率(就是參照源碼)
		public JarryReentrantLock() {
			this.isFair = false;
		}
	
		public JarryReentrantLock(boolean isFair) {
			this.isFair = isFair;
		}
	
		private CommonMask commonMask = new CommonMask(){
	
			@Override
			public boolean tryLock(int acquires){
				if (isFair){
					return tryFairLock(acquires);
				} else {
					return tryNonFairLock(acquires);
				}
			}
	
			private boolean tryFairLock(int acquires){
				// 這里簡單注釋一下,如何實現公平鎖,其關鍵在於新的線程到來時,不再直接嘗試獲取鎖,而是直接塞入隊列(隊列為空,也是殊途同歸的)
				// 1.判斷讀鎖(共享鎖)是否被占用
				if (readCount.get() == 0){
					// 2.判斷寫鎖(獨占鎖)是否被占用
					int writeCountValue = writeCount.get();
					if (writeCountValue == 0){
						// 2.1 (核心區別)如果寫鎖未被占用,需要先對等待隊列waiters進行判斷
						WaitNode head = waiters.peek();
						if (head !=null && head.thread == Thread.currentThread()){
							if (writeCount.compareAndSet(writeCountValue,writeCountValue+acquires)){
								owner.set(Thread.currentThread());
								return true;
							}	// 競爭失敗就直接返回false了
						}
					} else {
						// 2.2 如果寫鎖已經被占用了,就判斷是否為當前線程持有,是否進行重入操作
						if (owner.get() == Thread.currentThread()){
							// 如果持有獨占鎖的線程就是當前線程,那么不需要改變owner,也不需要CAS,只需要修改writeCount的值即可
							writeCount.set(writeCountValue + acquires);
							return true;
						}
					}
				}
				// 以上操作失敗,就返回false,表示競爭鎖失敗
				return false;
			}
	
			private boolean tryNonFairLock(int acquires){
				if (readCount.get() == 0){
					int writeCountValue = writeCount.get();
					if (writeCountValue == 0){
						if (writeCount.compareAndSet(writeCountValue,writeCountValue+acquires)){
							owner.set(Thread.currentThread());
							return true;
						}
					} else {
						if (Thread.currentThread() == owner.get()){
							writeCount.set(writeCountValue+acquires);
							return true;
						}
					}
				}
				return false;
			}
	
			@Override
			public boolean tryUnlock(int releases) {
				if (owner.get() != Thread.currentThread()){
					throw new IllegalMonitorStateException();
				}
				int writeCountValue = writeCount.get();
				writeCount.set(writeCountValue-releases);
				if (writeCount.get() == 0){
					owner.compareAndSet(Thread.currentThread(),null);
					return true;
				} else {
					return false;
				}
			}
	
			// 其它諸如共享鎖的相關操作,就不進行了。如果強行調用,只會發生UnsupportedOperationException
		};
	
		public void lock() {
			commonMask.lock();
		}
	
		public void unlock() {
			commonMask.unlock();
		}
	
		public boolean tryLock(int acquire) {
			return commonMask.tryLock(acquire);
		}
	
		private boolean tryUnlock(int release) {
			return commonMask.tryUnlock(release);
		}
	}

3.JarryReadWriteLock:


	package tech.jarry.learning.netease.locks4;
	
	/**
	 * @Description:
	 * @Author: jarry
	 */
	public class JarryReadWriteLock {
	
		private CommonMask commonMask = new CommonMask(){
	
			@Override
			public boolean tryLock(int acquires){
				if (readCount.get() == 0){
					int writeCountValue = writeCount.get();
					if (writeCountValue == 0){
						if (writeCount.compareAndSet(writeCountValue,writeCountValue+acquires)){
							owner.set(Thread.currentThread());
							return true;
						}
					} else {
						if (Thread.currentThread() == owner.get()){
							writeCount.set(writeCountValue+acquires);
							return true;
						}
					}
				}
				return false;
			}
	
			@Override
			public boolean tryUnlock(int releases) {
				if (owner.get() != Thread.currentThread()){
					throw new IllegalMonitorStateException();
				}
				int writeCountValue = writeCount.get();
				writeCount.set(writeCountValue-releases);
				if (writeCount.get() == 0){
					owner.compareAndSet(Thread.currentThread(),null);
					return true;
				} else {
					return false;
				}
			}
	
			@Override
			public boolean tryLockShared(int acquires) {
				while (true){
					if (writeCount.get() == 0 || owner.get() == Thread.currentThread()){
						int readCountValue = readCount.get();
						if (readCount.compareAndSet(readCountValue, readCountValue+acquires)){
							return true;
						}
					}
					return false;
				}
			}
	
			@Override
			public boolean tryUnLockShared(int releases) {
				while (true){
					int readCountValue = readCount.get();
					int readCountNext = readCountValue - releases;
					if (readCount.compareAndSet(readCountValue,readCountNext)){
						return readCountNext == 0;
					}
				}
			}
		};
	
	
		/**
		 * 獲取獨占鎖(針對獨占鎖)
		 */
		public void lock(){
			commonMask.lock();
		}
	
		/**
		 * 解鎖(針對獨占鎖)
		 */
		public void unlock(){
			commonMask.unlock();
		}
	
		/**
		 * 嘗試獲取獨占鎖(針對獨占鎖)
		 * @param acquires 用於加鎖次數。一般傳入waitNode.arg(本代碼中就是1。為什么不用一個常量1,就不知道了?)
		 * @return
		 */
		public boolean tryLock(int acquires){
			return commonMask.tryLock(acquires);
		}
	
		/**
		 * 嘗試解鎖(針對獨占鎖)
		 * @param releases 用於設定解鎖次數。一般傳入waitNode.arg
		 * @return
		 */
		public boolean tryUnlock(int releases){
			return commonMask.tryUnlock(releases);
		}
	
		/**
		 * 獲取共享鎖(針對共享鎖)
		 */
		public void lockShared(){
			commonMask.lockShared();
		}
	
		/**
		 * 解鎖(針對共享鎖)
		 */
		public boolean unLockShared(){
			return commonMask.unLockShared();
		}
	
		/**
		 * 嘗試獲取共享鎖(針對共享鎖)
		 * @param acquires
		 * @return
		 */
		public boolean tryLockShared(int acquires){
			return tryLockShared(acquires);
		}
	
		/**
		 * 嘗試解鎖(針對共享鎖)
		 * @param releases
		 * @return
		 */
		public boolean tryUnLockShared(int releases){
			return commonMask.tryUnLockShared(releases);
		}
	
	}

這樣看來,順眼不少。但是,還是存在兩點問題。一方面,兩個Lock並沒有如實際源碼那樣,實現Lock接口與ReadWriteLock接口。另一方面,JarryReadWriteLock並沒有如實際源碼那樣,通過獲取對應Lock(如ReadLock與WriteLock),再進行對應鎖操作(其實,就是實現ReadWriteLock接口)。

那么就來進行改造吧。這里直接采用James大佬的最終版CommonMask-JameAQS了。 這里采用自己的AQS,因為自己的AQS有一些關鍵注解。

四,簡易JUC(版本四):

1.JarryAQS:


	package tech.jarry.learning.netease.locks6;
	
	import java.util.concurrent.LinkedBlockingQueue;
	import java.util.concurrent.atomic.AtomicInteger;
	import java.util.concurrent.atomic.AtomicReference;
	import java.util.concurrent.locks.LockSupport;
	
	/**
	 * @Description:
	 * @Author: jarry
	 */
	public class JarryAQS {
	
		volatile AtomicInteger readCount = new AtomicInteger(0);
		AtomicInteger writeCount = new AtomicInteger(0);
		AtomicReference<Thread> owner = new AtomicReference<>();
		public volatile LinkedBlockingQueue<WaitNode> waiters = new LinkedBlockingQueue<>();
	
		class WaitNode{
			Thread thread = null;
			// 表示希望爭取的鎖的類型。0表示寫鎖(獨占鎖),1表示讀鎖(共享鎖)
			int type = 0;
			int arg = 0;
	
			public WaitNode(Thread thread, int type, int arg) {
				this.type = type;
				this.thread = thread;
				this.arg = arg;
			}
		}
	
		/**
		 * 獲取獨占鎖(針對獨占鎖)
		 */
		public void lock(){
			int arg = 1;
			if (!tryLock(arg)){
				WaitNode waitNode = new WaitNode(Thread.currentThread(), 0, arg);
				waiters.offer(waitNode);
	
				while (true){
					WaitNode headNote = waiters.peek();
					if (headNote !=null && headNote.thread == Thread.currentThread()){
						if (!tryLock(headNote.arg)){
							LockSupport.park();
						} else {
							waiters.poll();
							return;
						}
					}else {
						LockSupport.park();
					}
				}
			}
		}
	
		/**
		 * 解鎖(針對獨占鎖)
		 */
		public void unlock(){
			int arg = 1;
			if (tryUnlock(arg)){
				WaitNode head = waiters.peek();
				if (head == null){
					return;
				}
				LockSupport.unpark(head.thread);
			}
		}
	
	
		/**
		 * 獲取共享鎖(針對共享鎖)
		 */
		public void lockShared(){
			int arg = 1;
			if (!tryLockShared(arg)){
				WaitNode waitNode = new WaitNode(Thread.currentThread(),1,arg);
				waiters.offer(waitNode);
	
				while (true){
					WaitNode head = waiters.peek();
					if (head != null && head.thread == Thread.currentThread()){
						if (tryLockShared(head.arg)){
							waiters.poll();
	
							WaitNode newHead = waiters.peek();
							if (newHead != null && newHead.type == 1){
								LockSupport.unpark(newHead.thread);
							}
							return;
						} else {
							LockSupport.park();
						}
					} else {
						LockSupport.park();
					}
				}
			}
		}
	
		/**
		 * 解鎖(針對共享鎖)
		 */
		public boolean unLockShared(){
			int arg = 1;
			if (tryUnLockShared(arg)){
				WaitNode head = waiters.peek();
				if (head != null){
					LockSupport.unpark(head.thread);
				}
				return true;
			}
			return false;
		}
	
		/**
		 * 嘗試獲取獨占鎖(針對獨占鎖)
		 * @param acquires
		 * @return
		 */
		public boolean tryLock(int acquires){
			throw new UnsupportedOperationException();
		}
	
		/**
		 * 嘗試解鎖(針對獨占鎖)
		 * @param releases 用於設定解鎖次數。一般傳入waitNode.arg
		 * @return
		 */
		public boolean tryUnlock(int releases){
			throw new UnsupportedOperationException();
		}
	
		/**
		 * 嘗試獲取共享鎖(針對共享鎖)
		 * @param acquires
		 * @return
		 */
		public boolean tryLockShared(int acquires){
			throw new UnsupportedOperationException();
		}
	
		/**
		 * 嘗試解鎖(針對共享鎖)
		 * @param releases
		 * @return
		 */
		public boolean tryUnLockShared(int releases){
			throw new UnsupportedOperationException();
		}
	}

2.JarryReentrantLock:

	
	package tech.jarry.learning.netease.locks6;
	
	import java.util.concurrent.TimeUnit;
	import java.util.concurrent.locks.Condition;
	import java.util.concurrent.locks.Lock;
	
	/**
	 * @Description: 仿ReentrantLock,實現其基本功能及特性
	 * @Author: jarry
	 */
	public class JarryReentrantLock implements Lock {
	
		private boolean isFair;
	
		// 默認采用非公平鎖,保證效率(就是參照源碼)
		public JarryReentrantLock() {
			this.isFair = false;
		}
	
		public JarryReentrantLock(boolean isFair) {
			this.isFair = isFair;
		}
	
		private JarryAQS jarryAQS = new JarryAQS(){
	
			@Override
			// 源碼中,則是將FairSync與NonFairSync作為兩個單獨內布類(extend Sync),來實現的。那樣會更加優雅,耦合度更低,擴展性更好(而且實際源碼,需要重寫的部分也會更多,而不像這個自定義demo,只有一個tryLock方法需要重寫)
			public boolean tryLock(int acquires){
				if (isFair){
					return tryFairLock(acquires);
				} else {
					return tryNonFairLock(acquires);
				}
			}
	
			private boolean tryFairLock(int acquires){
				// 這里簡單注釋一下,如何實現公平鎖,其關鍵在於新的線程到來時,不再直接嘗試獲取鎖,而是直接塞入隊列(隊列為空,也是殊途同歸的)
				// 1.判斷讀鎖(共享鎖)是否被占用
				if (readCount.get() == 0){
					// 2.判斷寫鎖(獨占鎖)是否被占用
					int writeCountValue = writeCount.get();
					if (writeCountValue == 0){
						// 2.1 (核心區別)如果寫鎖未被占用,需要先對等待隊列waiters進行判斷
						WaitNode head = waiters.peek();
						if (head !=null && head.thread == Thread.currentThread()){
							if (writeCount.compareAndSet(writeCountValue,writeCountValue+acquires)){
								owner.set(Thread.currentThread());
								return true;
							}	// 競爭失敗就直接返回false了
						}
					} else {
						// 2.2 如果寫鎖已經被占用了,就判斷是否為當前線程持有,是否進行重入操作
						if (owner.get() == Thread.currentThread()){
							// 如果持有獨占鎖的線程就是當前線程,那么不需要改變owner,也不需要CAS,只需要修改writeCount的值即可
							writeCount.set(writeCountValue + acquires);
							return true;
						}
					}
				}
				// 以上操作失敗,就返回false,表示競爭鎖失敗
				return false;
			}
	
			private boolean tryNonFairLock(int acquires){
				if (readCount.get() == 0){
					int writeCountValue = writeCount.get();
					if (writeCountValue == 0){
						if (writeCount.compareAndSet(writeCountValue,writeCountValue+acquires)){
							owner.set(Thread.currentThread());
							return true;
						}
					} else {
						if (Thread.currentThread() == owner.get()){
							writeCount.set(writeCountValue+acquires);
							return true;
						}
					}
				}
				return false;
			}
	
			@Override
			/**
			 *
			 先通過臨時變量c,判斷是否接下來的操作會完全解鎖。
			 如果完全解鎖,先釋放owner,再通過setState將count(源碼中為state)修改為0。
			 這樣調換了一下順序,但是避免了owner的原子性問題(畢竟別的線程是通過state來判斷是否可以競爭鎖,修改owner的)。
			 */
			public boolean tryUnlock(int releases) {
				if (owner.get() != Thread.currentThread()){
					throw new IllegalMonitorStateException();
				}
				int writeCountNextValue = writeCount.get() - releases;
				boolean result = false;
				if (writeCountNextValue == 0){
					result = true;
					owner.set(null);
				}
				writeCount.set(writeCountNextValue);
				return result;
			}
	
			// 其它諸如共享鎖的相關操作,就不進行了。如果強行調用,只會發生UnsupportedOperationException
		};
	
		@Override
		public void lock() {
			jarryAQS.lock();
		}
	
		@Override
		public void lockInterruptibly() throws InterruptedException {
	
		}
	
		@Override
		public boolean tryLock() {
			return jarryAQS.tryLock(1);
		}
	
		@Override
		public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
			return false;
		}
	
		@Override
		public void unlock() {
			jarryAQS.unlock();
		}
	
		@Override
		public Condition newCondition() {
			return null;
		}
	
	}

3.JarryReadWriteLock:

	
	package tech.jarry.learning.netease.locks6;
	
	import java.util.concurrent.TimeUnit;
	import java.util.concurrent.locks.Condition;
	import java.util.concurrent.locks.Lock;
	import java.util.concurrent.locks.ReadWriteLock;
	
	/**
	 * @Description:
	 * @Author: jarry
	 */
	public class JarryReadWriteLock implements ReadWriteLock {
	
		private JarryAQS jarryAQS = new JarryAQS(){
	
			@Override
			// 實際源碼,是通過Sync類,繼承AQS,再進行Override的。
			public boolean tryLock(int acquires){
				if (readCount.get() == 0){
					int writeCountValue = writeCount.get();
					if (writeCountValue == 0){
						if (writeCount.compareAndSet(writeCountValue,writeCountValue+acquires)){
							owner.set(Thread.currentThread());
							return true;
						}
					} else {
						if (Thread.currentThread() == owner.get()){
							writeCount.set(writeCountValue+acquires);
							return true;
						}
					}
				}
				return false;
			}
	
			@Override
			public boolean tryUnlock(int releases) {
				if (owner.get() != Thread.currentThread()){
					throw new IllegalMonitorStateException();
				}
				int writeCountNextValue = writeCount.get() - releases;
				boolean result = false;
				if (writeCountNextValue == 0){
					result = true;
					owner.set(null);
				}
				writeCount.set(writeCountNextValue);
				return result;
			}
	
			@Override
			public boolean tryLockShared(int acquires) {
				while (true){
					if (writeCount.get() == 0 || owner.get() == Thread.currentThread()){
						int readCountValue = readCount.get();
						if (readCount.compareAndSet(readCountValue, readCountValue+acquires)){
							return true;
						}
					}
					return false;
				}
			}
	
			@Override
			public boolean tryUnLockShared(int releases) {
				while (true){
					int readCountValue = readCount.get();
					int readCountNext = readCountValue - releases;
					if (readCount.compareAndSet(readCountValue,readCountNext)){
						return readCountNext == 0;
					}
				}
			}
		};
	
	
		/**
		 * 獲取獨占鎖(針對獨占鎖)
		 */
		public void lock(){
			jarryAQS.lock();
		}
	
		/**
		 * 解鎖(針對獨占鎖)
		 */
		public void unlock(){
			jarryAQS.unlock();
		}
	
		/**
		 * 嘗試獲取獨占鎖(針對獨占鎖)
		 * @param acquires 用於加鎖次數。一般傳入waitNode.arg(本代碼中就是1。為什么不用一個常量1,就不知道了?)
		 * @return
		 */
		public boolean tryLock(int acquires){
			return jarryAQS.tryLock(acquires);
		}
	
		/**
		 * 嘗試解鎖(針對獨占鎖)
		 * @param releases 用於設定解鎖次數。一般傳入waitNode.arg
		 * @return
		 */
		public boolean tryUnlock(int releases){
			return jarryAQS.tryUnlock(releases);
		}
	
		/**
		 * 獲取共享鎖(針對共享鎖)
		 */
		public void lockShared(){
			jarryAQS.lockShared();
		}
	
		/**
		 * 解鎖(針對共享鎖)
		 */
		public boolean unLockShared(){
			return jarryAQS.unLockShared();
		}
	
		/**
		 * 嘗試獲取共享鎖(針對共享鎖)
		 * @param acquires
		 * @return
		 */
		public boolean tryLockShared(int acquires){
			return tryLockShared(acquires);
		}
	
		/**
		 * 嘗試解鎖(針對共享鎖)
		 * @param releases
		 * @return
		 */
		public boolean tryUnLockShared(int releases){
			return jarryAQS.tryUnLockShared(releases);
		}
	
		@Override
		public Lock readLock() {
			return new Lock() {
				@Override
				public void lock() {
					jarryAQS.lockShared();
				}
	
				@Override
				public void lockInterruptibly() throws InterruptedException {
	
				}
	
				@Override
				public boolean tryLock() {
					return jarryAQS.tryLockShared(1);
				}
	
				@Override
				public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
					return false;
				}
	
				@Override
				public void unlock() {
					jarryAQS.unLockShared();
				}
	
				@Override
				public Condition newCondition() {
					return null;
				}
			};
		}
	
		@Override
		public Lock writeLock() {
			return new Lock() {
				@Override
				public void lock() {
					jarryAQS.lock();
				}
	
				@Override
				public void lockInterruptibly() throws InterruptedException {
	
				}
	
				@Override
				public boolean tryLock() {
					return jarryAQS.tryLock(1);
				}
	
				@Override
				public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
					return false;
				}
	
				@Override
				public void unlock() {
					jarryAQS.unlock();
				}
	
				@Override
				public Condition newCondition() {
					return null;
				}
			};
		}
	}

到了這里,其實JUC的核心-AQS,已經揭露出來了。通過這個,就可以把握住AQS核心運行機制。而實際的AQS,無非就是修改了存儲線程的WaitNodes,采用了Node形成鏈表。並通過head與tail的應用,來提高效率。當然還有lockInterruptibly等沒有提及,也有Condition這樣的大頭沒有說。這部分就留待以后有機會,再深入吧。

另外,再給出這方面的提升道路。如果希望更加深入理解AQS源碼,可以一邊閱讀源碼(思考源碼實現與自己實現的區別),一邊擴展自定義簡易AQS。

如,我了解到AQS是通過一個state來同時實現獨占鎖與共享鎖的持有數量。那么我就在JarryAQS中,去嘗試實現,從而進一步理解它。

五,簡易JUC(版本X-擴展state):

1.JarryAQS:


	package tech.jarry.learning.netease.locks7;
	
	import sun.misc.Unsafe;
	
	import java.lang.reflect.Field;
	import java.util.concurrent.LinkedBlockingQueue;
	import java.util.concurrent.atomic.AtomicInteger;
	import java.util.concurrent.atomic.AtomicReference;
	import java.util.concurrent.locks.LockSupport;
	
	/**
	 * @Description:
	 * @Author: jarry
	 */
	public class JarryAQS {
	
		static final int SHARED_SHIFT   = 16;
		static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
		static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
		static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
	
		/** Returns the number of shared holds represented in count  */
		static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
		/** Returns the number of exclusive holds represented in count  */
		static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
	
		/**
		 * The synchronization state.
		 */
		public volatile int state;
		private static Unsafe unsafe;
		private static long stateOffset;
		static{
			try {
				Field field = Unsafe.class.getDeclaredField("theUnsafe");
				field.setAccessible(true);
				unsafe = (Unsafe) field.get(null);
	
				Field fieldi = JarryAQS.class.getDeclaredField("state");
				stateOffset = unsafe.objectFieldOffset(fieldi);
	
			} catch (NoSuchFieldException | IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		protected final boolean compareAndSetState(int expect, int update) {
			// See below for intrinsics setup to support this
			return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
		}
	
	
		
		volatile AtomicInteger readCount = new AtomicInteger(0);
		AtomicInteger writeCount = new AtomicInteger(0);
	
		AtomicReference<Thread> owner = new AtomicReference<>();
		public volatile LinkedBlockingQueue<WaitNode> waiters = new LinkedBlockingQueue<>();
	
		class WaitNode{
			Thread thread = null;
			// 表示希望爭取的鎖的類型。0表示寫鎖(獨占鎖),1表示讀鎖(共享鎖)
			int type = 0;
			int arg = 0;
	
			public WaitNode(Thread thread, int type, int arg) {
				this.type = type;
				this.thread = thread;
				this.arg = arg;
			}
		}
	
		/**
		 * 獲取獨占鎖(針對獨占鎖)
		 */
		public void lock(){
			int arg = 1;
			if (!tryLock(arg)){
				WaitNode waitNode = new WaitNode(Thread.currentThread(), 0, arg);
				waiters.offer(waitNode);
	
				while (true){
					WaitNode headNote = waiters.peek();
					if (headNote !=null && headNote.thread == Thread.currentThread()){
						if (!tryLock(headNote.arg)){
							LockSupport.park();
						} else {
							waiters.poll();
							return;
						}
					}else {
						LockSupport.park();
					}
				}
			}
		}
	
		/**
		 * 解鎖(針對獨占鎖)
		 */
		public void unlock(){
			int arg = 1;
			if (tryUnlock(arg)){
				WaitNode head = waiters.peek();
				if (head == null){
					return;
				}
				LockSupport.unpark(head.thread);
			}
		}
	
	
		/**
		 * 獲取共享鎖(針對共享鎖)
		 */
		public void lockShared(){
			int arg = 1;
			if (!tryLockShared(arg)){
				WaitNode waitNode = new WaitNode(Thread.currentThread(),1,arg);
				waiters.offer(waitNode);
	
				while (true){
					WaitNode head = waiters.peek();
					if (head != null && head.thread == Thread.currentThread()){
						if (tryLockShared(head.arg)){
							waiters.poll();
	
							WaitNode newHead = waiters.peek();
							if (newHead != null && newHead.type == 1){
								LockSupport.unpark(newHead.thread);
							}
							return;
						} else {
							LockSupport.park();
						}
					} else {
						LockSupport.park();
					}
				}
			}
		}
	
		/**
		 * 解鎖(針對共享鎖)
		 */
		public boolean unLockShared(){
			int arg = 1;
			if (tryUnLockShared(arg)){
				WaitNode head = waiters.peek();
				if (head != null){
					LockSupport.unpark(head.thread);
				}
				return true;
			}
			return false;
		}
	
		/**
		 * 嘗試獲取獨占鎖(針對獨占鎖)
		 * @param acquires
		 * @return
		 */
		public boolean tryLock(int acquires){
			throw new UnsupportedOperationException();
		}
	
		/**
		 * 嘗試解鎖(針對獨占鎖)
		 * @param releases 用於設定解鎖次數。一般傳入waitNode.arg
		 * @return
		 */
		public boolean tryUnlock(int releases){
			throw new UnsupportedOperationException();
		}
	
		/**
		 * 嘗試獲取共享鎖(針對共享鎖)
		 * @param acquires
		 * @return
		 */
		public boolean tryLockShared(int acquires){
			throw new UnsupportedOperationException();
		}
	
		/**
		 * 嘗試解鎖(針對共享鎖)
		 * @param releases
		 * @return
		 */
		public boolean tryUnLockShared(int releases){
			throw new UnsupportedOperationException();
		}
	}

2.JarryReentrantLock:


	package tech.jarry.learning.netease.locks7;
	
	import java.util.concurrent.TimeUnit;
	import java.util.concurrent.locks.Condition;
	import java.util.concurrent.locks.Lock;
	
	/**
	 * @Description: 仿ReentrantLock,實現其基本功能及特性
	 * @Author: jarry
	 */
	public class JarryReentrantLock implements Lock {
	
		private boolean isFair;
	
		// 默認采用非公平鎖,保證效率(就是參照源碼)
		public JarryReentrantLock() {
			this.isFair = false;
		}
	
		public JarryReentrantLock(boolean isFair) {
			this.isFair = isFair;
		}
	
		// 實際源碼,是通過Sync類,繼承AQS,再進行Override的。
		private JarryAQS jarryAQS = new JarryAQS(){
	
			@Override
			// 源碼中,則是將FairSync與NonFairSync作為兩個單獨內布類(extend Sync),來實現的。那樣會更加優雅,耦合度更低,擴展性更好(而且實際源碼,需要重寫的部分也會更多,而不像這個自定義demo,只有一個tryLock方法需要重寫)
			public boolean tryLock(int acquires){
				if (isFair){
					return tryFairLock(acquires);
				} else {
					return tryNonFairLock(acquires);
				}
			}
	
			private boolean tryFairLock(int acquires){
				// 這里簡單注釋一下,如何實現公平鎖,其關鍵在於新的線程到來時,不再直接嘗試獲取鎖,而是直接塞入隊列(隊列為空,也是殊途同歸的)
				// 1.判斷讀鎖(共享鎖)是否被占用
				if (readCount.get() == 0){
					// 2.判斷寫鎖(獨占鎖)是否被占用
					int writeCountValue = writeCount.get();
					if (writeCountValue == 0){
						// 2.1 (核心區別)如果寫鎖未被占用,需要先對等待隊列waiters進行判斷
						WaitNode head = waiters.peek();
						if (head !=null && head.thread == Thread.currentThread()){
							if (writeCount.compareAndSet(writeCountValue,writeCountValue+acquires)){
								owner.set(Thread.currentThread());
								return true;
							}	// 競爭失敗就直接返回false了
						}
					} else {
						// 2.2 如果寫鎖已經被占用了,就判斷是否為當前線程持有,是否進行重入操作
						if (owner.get() == Thread.currentThread()){
							// 如果持有獨占鎖的線程就是當前線程,那么不需要改變owner,也不需要CAS,只需要修改writeCount的值即可
							writeCount.set(writeCountValue + acquires);
							return true;
						}
					}
				}
				// 以上操作失敗,就返回false,表示競爭鎖失敗
				return false;
			}
	
			private boolean tryNonFairLock(int acquires){
				if (readCount.get() == 0){
					int writeCountValue = writeCount.get();
					if (writeCountValue == 0){
						if (writeCount.compareAndSet(writeCountValue,writeCountValue+acquires)){
							owner.set(Thread.currentThread());
							return true;
						}
					} else {
						if (Thread.currentThread() == owner.get()){
							writeCount.set(writeCountValue+acquires);
							return true;
						}
					}
				}
				return false;
			}
	
			@Override
			/**
			 *
			 先通過臨時變量c,判斷是否接下來的操作會完全解鎖。
			 如果完全解鎖,先釋放owner,再通過setState將count(源碼中為state)修改為0。
			 這樣調換了一下順序,但是避免了owner的原子性問題(畢竟別的線程是通過state來判斷是否可以競爭鎖,修改owner的)。
			 */
			public boolean tryUnlock(int releases) {
				if (owner.get() != Thread.currentThread()){
					throw new IllegalMonitorStateException();
				}
				int writeCountNextValue = writeCount.get() - releases;
				boolean result = false;
				if (writeCountNextValue == 0){
					result = true;
					owner.set(null);
				}
				writeCount.set(writeCountNextValue);
				return result;
			}
	
			// 其它諸如共享鎖的相關操作,就不進行了。如果強行調用,只會發生UnsupportedOperationException
		};
	
		@Override
		public void lock() {
			jarryAQS.lock();
		}
	
		@Override
		public void lockInterruptibly() throws InterruptedException {
	
		}
	
		@Override
		public boolean tryLock() {
			return jarryAQS.tryLock(1);
		}
	
		@Override
		public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
			return false;
		}
	
		@Override
		public void unlock() {
			jarryAQS.unlock();
		}
	
		@Override
		public Condition newCondition() {
			return null;
		}
	
	}

3.JarryReadWriteLock:


	package tech.jarry.learning.netease.locks7;
	
	import java.util.concurrent.TimeUnit;
	import java.util.concurrent.locks.Condition;
	import java.util.concurrent.locks.Lock;
	import java.util.concurrent.locks.ReadWriteLock;
	
	/**
	 * @Description:
	 * @Author: jarry
	 */
	public class JarryReadWriteLock implements ReadWriteLock {
	
		// 實際源碼,是通過Sync類,繼承AQS,再進行Override的。
		private JarryAQS jarryAQS = new JarryAQS(){
	
			@Override
			public boolean tryLock(int acquires){
				int stateTemp = state;
				if (sharedCount(stateTemp) == 0){
					int writeCountValue = exclusiveCount(stateTemp);
					if (writeCountValue == 0){
						if (compareAndSetState(stateTemp,stateTemp+acquires)){
							owner.set(Thread.currentThread());
							return true;
						}
					} else {
						if (Thread.currentThread() == owner.get()){
							compareAndSetState(stateTemp,stateTemp+acquires);
							return true;
						}
					}
				}
				return false;
			}
	
			@Override
			public boolean tryUnlock(int releases) {
				int stateTemp = state;
				if (owner.get() != Thread.currentThread()){
					throw new IllegalMonitorStateException();
				}
				int writeCountNextValue = exclusiveCount(stateTemp) - releases;
				boolean result = false;
				if (writeCountNextValue == 0){
					result = true;
					owner.set(null);
				}
				compareAndSetState(stateTemp,stateTemp - releases);
				return result;
			}
	
			@Override
			public boolean tryLockShared(int acquires) {
				while (true){
					int stateTemp = state;
					if (exclusiveCount(stateTemp) == 0 || owner.get() == Thread.currentThread()){
						if (compareAndSetState(stateTemp, stateTemp+SHARED_UNIT*acquires)){
							return true;
						}
					}
					return false;
				}
			}
	
			@Override
			public boolean tryUnLockShared(int releases) {
				while (true){
					int stateTemp = state;
					int readCountValue = sharedCount(stateTemp);
					int readCountNext = readCountValue - releases;
					if (compareAndSetState(stateTemp, stateTemp-SHARED_UNIT*readCountNext)){
						return readCountNext == 0;
					}
				}
			}
		};
	
	
		/**
		 * 獲取獨占鎖(針對獨占鎖)
		 */
		public void lock(){
			jarryAQS.lock();
		}
	
		/**
		 * 解鎖(針對獨占鎖)
		 */
		public void unlock(){
			jarryAQS.unlock();
		}
	
		/**
		 * 嘗試獲取獨占鎖(針對獨占鎖)
		 * @param acquires 用於加鎖次數。一般傳入waitNode.arg(本代碼中就是1。為什么不用一個常量1,就不知道了?)
		 * @return
		 */
		public boolean tryLock(int acquires){
			return jarryAQS.tryLock(acquires);
		}
	
		/**
		 * 嘗試解鎖(針對獨占鎖)
		 * @param releases 用於設定解鎖次數。一般傳入waitNode.arg
		 * @return
		 */
		public boolean tryUnlock(int releases){
			return jarryAQS.tryUnlock(releases);
		}
	
		/**
		 * 獲取共享鎖(針對共享鎖)
		 */
		public void lockShared(){
			jarryAQS.lockShared();
		}
	
		/**
		 * 解鎖(針對共享鎖)
		 */
		public boolean unLockShared(){
			return jarryAQS.unLockShared();
		}
	
		/**
		 * 嘗試獲取共享鎖(針對共享鎖)
		 * @param acquires
		 * @return
		 */
		public boolean tryLockShared(int acquires){
			return tryLockShared(acquires);
		}
	
		/**
		 * 嘗試解鎖(針對共享鎖)
		 * @param releases
		 * @return
		 */
		public boolean tryUnLockShared(int releases){
			return jarryAQS.tryUnLockShared(releases);
		}
	
		@Override
		public Lock readLock() {
			return new Lock() {
				@Override
				public void lock() {
					jarryAQS.lockShared();
				}
	
				@Override
				public void lockInterruptibly() throws InterruptedException {
	
				}
	
				@Override
				public boolean tryLock() {
					return jarryAQS.tryLockShared(1);
				}
	
				@Override
				public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
					return false;
				}
	
				@Override
				public void unlock() {
					jarryAQS.unLockShared();
				}
	
				@Override
				public Condition newCondition() {
					return null;
				}
			};
		}
	
		@Override
		public Lock writeLock() {
			return new Lock() {
				@Override
				public void lock() {
					jarryAQS.lock();
				}
	
				@Override
				public void lockInterruptibly() throws InterruptedException {
	
				}
	
				@Override
				public boolean tryLock() {
					return jarryAQS.tryLock(1);
				}
	
				@Override
				public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
					return false;
				}
	
				@Override
				public void unlock() {
					jarryAQS.unlock();
				}
	
				@Override
				public Condition newCondition() {
					return null;
				}
			};
		}
	}

六,總結:

如果是從ReentrantLock實現,一步步走到這里,手動擼到這里,那么你對AQS的認知,就有了非常堅實的基礎。如果能夠在學習過程中,對照源碼學習(一邊自己實現,一邊了解源碼是怎么解決相關問題的),那么你對AQS的理解就很不錯了。即使有所欠缺,也只是AQS閱讀積累方面了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM