J.U.C剖析与解读2(AQS的由来) (2)

很明显,上面的代码中,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); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzxzzz.html