主要针对AQS原理进行巩固,利用自定义的同步器实现不可重入锁
自定义锁
部分方法直接使用父类的同步器实现的
public class NonReentrantLock implements Lock {private final NonReentrantSync sync = new NonReentrantSync();// 尝试,不成功,进入等待队列@Overridepublic void lock() {sync.acquire(1);}// 尝试,不成功,进入等待队列,可打断@Overridepublic void lockInterruptibly() throws InterruptedException {sync.acquireSharedInterruptibly(1);}//尝试一次,不成功返回,不进入队列@Overridepublic boolean tryLock() {return sync.tryAcquire(1);}/*** @throws* @description 尝试,不成功,进入等待队列,有时限* @author SongHongWei* @params* @updateTime 2021/10/5 12:21*/@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {return sync.tryAcquireSharedNanos(1, unit.toNanos(time));}//释放锁@Overridepublic void unlock() {sync.release(1);}//生成条件变量@Overridepublic Condition newCondition() {return sync.newCondition();}}
自定义同步器
只是实现了独占锁的实现方法
public class NonReentrantSync extends AbstractQueuedSynchronizer {protected Condition newCondition() {return new ConditionObject();}/*** @throws* @description 尝试获取资源,立即返回。成功则返回true,否则false。* @author SongHongWei* @params* @updateTime 2021/10/5 12:14*/@Overrideprotected boolean tryAcquire(int arg) {// 这里限定只能为1个量if (arg == 1) {//state为0才设置为1,不可重入if (compareAndSetState(0, 1)) {//设置为当前线程独占资源setExclusiveOwnerThread(Thread.currentThread());return true;}}return false;}/*** @throws* @description 尝试释放资源,立即返回。成功则为true,否则false。* @author SongHongWei* @params* @updateTime 2021/10/5 12:17*/@Overrideprotected boolean tryRelease(int arg) {//限定为1个量if(arg == 1) {///既然来释放,那肯定就是已占有状态了。只是为了保险,多层判断if(getState() == 0) {throw new IllegalMonitorStateException();}setExclusiveOwnerThread(null);//释放资源,放弃占有状态setState(0);return true;}return false;}@Overrideprotected boolean isHeldExclusively() {return getState() == 1;}
测试类
测试结果,t1线程始终获取不到第二次锁
public class AqsClient {static final NonReentrantLock lock = new NonReentrantLock();public static void main(String[] args) {log.info("主线程启动....");new Thread(() -> {lock.lock();log.info("线程t1第一次获取锁...");try {log.info("线程t1尝试再次获取锁...");lock.lock();log.info("线程t1再次获取锁成功");lock.unlock();log.info("线程t1释放重入锁...");} finally {lock.unlock();log.info("线程t1释放锁");}}, "t1").start();}}
