重新整理思路,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); } }