简单独占锁实现
学习AQS、ReentrantLock和CountDownLatch有感,根据原理写了一个简单的独占锁的demo。
首先是极简AQS(AbstractQueuedSynchronizer)类
AbstractQueuedSimpleSynchronizer
package com.sephy.test.abstractlock; import java.util.concurrent.locks.AbstractQueuedSynchronizer; /** * @version V1.0 * @功能描述: * @名称: com.sephy.test.abstractlock.AbstractQuenedSimpleSync * @作者 Sephy * @创建时间 2021-10-01 14:50 */ public abstract class AbstractQueuedSimpleSynchronizer { //锁状态 0-free 1-locked private volatile int state; private Thread owner; protected final int getState() { return state; } protected final void setState(int newState) { state = newState; } protected final boolean compareAndSetState(int expect, int update){ if(getState() == expect){ //当前state大于更新后的state,说明要释放锁 if(expect > update){ System.out.println(Thread.currentThread().getName()+"释放锁成功!!!"); } //当前state小于更新后的state,说明要加锁 else if(expect < update){ System.out.println(Thread.currentThread().getName()+"加锁成功!!!"); } setState(update); return true; }else return false; } protected Thread getExclusiveOwnerThread(){ return owner; } /** * 获取独占锁 * @param arg * @throws InterruptedException */ public final void acquireExclusive(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireExclusive(arg) < 0) { //无锁,可加锁 doAcquireExclusive(arg); } else{ System.out.println(Thread.currentThread().getName()+"加锁失败~~~锁已经被"+owner.getName()+"占用"); } } //加锁 private void doAcquireExclusive(int arg) { if(compareAndSetState(0,1)){ owner = Thread.currentThread(); System.out.println(Thread.currentThread().getName()+"加锁成功!!!"); }else{ System.out.println(Thread.currentThread().getName()+"加锁失败~~~"+owner.getName()+"占用"); } } //获取独占锁,子类实现 abstract int tryAcquireExclusive(int arg); /** * 释放独占锁 * @param arg * @return */ public final boolean releaseExclusive(int arg) { if (owner == Thread.currentThread()) { if(tryReleaseExclusive(arg)){ doReleaseExclusive(arg); return true; }else{ System.out.println(Thread.currentThread().getName()+"释放锁失败~~~当前无锁"); return false; } } else{ System.out.println(Thread.currentThread().getName()+"释放锁失败~~~当前不是锁的使用者"+owner.getName()); return false; } } public void doReleaseExclusive(int arg) { // System.out.println(Thread.currentThread().getName()+"释放锁成功!!!"); } //释放独占锁,子类实现 abstract boolean tryReleaseExclusive(int arg); }
根据CountDownLatch的思想,实现简单的Lock
MyLock
package com.sephy.test.abstractlock; /** * @version V1.0 * @功能描述: * @名称: com.sephy.test.abstractlock.MyLock * @作者 Sephy * @创建时间 2021-10-01 15:15 */ public class MyLock { private static final class Sync extends AbstractQueuedSimpleSynchronizer { private static boolean wait = false; Sync(int state,boolean wait){ this.wait = wait; setState(state); } //1:free -1:locked @Override int tryAcquireExclusive(int arg) { if(wait){ //等待锁的释放 for(;;){ if(getState() == 0){ return -1; } } }else{ //只请求一次,锁被占用则返回 return (getState() == 0) ? -1 : 1; } } @Override boolean tryReleaseExclusive(int arg) { int c = getState(); if (c == 0) return false; int nextc = c-1; if (compareAndSetState(c, nextc)) return nextc == 0; return false; } } private final Sync sync; public MyLock(int count,boolean wait){ if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count,wait); } public void acquireLock() throws InterruptedException { sync.acquireExclusive(1); } public void releaseLock() { sync.releaseExclusive(1); } }
测试类
MyLockTest
package com.sephy.test.abstractlock; import lombok.SneakyThrows; /** * @version V1.0 * @功能描述: * @名称: com.sephy.test.abstractlock.MyLockTest * @作者 Sephy * @创建时间 2021-10-01 15:36 */ public class MyLockTest { public static void main(String[] args) { MyLock lock = new MyLock(0,true); Thread t1 = new Thread(new Runnable() { @SneakyThrows @Override public void run() { lock.acquireLock(); Thread.sleep(4000L); lock.releaseLock(); Thread.sleep(1000L); lock.releaseLock(); Thread.sleep(3000L); lock.acquireLock(); Thread.sleep(3000L); lock.releaseLock(); } }); Thread t2 = new Thread(new Runnable() { @SneakyThrows @Override public void run() { Thread.sleep(1000L); lock.acquireLock(); Thread.sleep(2000L); lock.releaseLock(); Thread.sleep(4000L); lock.acquireLock(); Thread.sleep(2000L); lock.releaseLock(); } }); t1.start(); t2.start(); } }
当wait=true时,结果
Thread-0加锁成功!!! Thread-0释放锁成功!!! Thread-1加锁成功!!! Thread-0释放锁失败~~~当前不是锁的使用者Thread-1 Thread-1释放锁成功!!! Thread-0加锁成功!!! Thread-0释放锁成功!!! Thread-1加锁成功!!! Thread-1释放锁成功!!!
当wait=false时,结果
Thread-0加锁成功!!! Thread-1加锁失败~~~锁已经被Thread-0占用 Thread-1释放锁失败~~~当前不是锁的使用者Thread-0 Thread-0释放锁成功!!! Thread-0释放锁失败~~~当前无锁 Thread-1加锁成功!!! Thread-0加锁失败~~~锁已经被Thread-1占用 Thread-1释放锁成功!!! Thread-0释放锁失败~~~当前不是锁的使用者Thread-1