1)概述
aqs全称AbstractQueuedSynchronizer【简称同步器】 ,是一个用来构建锁和同步工具的框架,ReentrantLock就是基于aqs构建的。这是一个抽象类,其子类中可以重写其中的各种同步操作方法来完成锁的实现。AQS同步器具有以下特点:
①aqs使用一个volatile修饰的原子变量state来表示锁的状态,具体代表什么状态可以由子类去定义,一般是用0代表未加锁,1代表已加锁,值得注意的是其中锁的状态的变化使用的是CAS操作;
②内部使用先进先出的队列来保存获取锁等待的线程对象,类似monitor中的EntryList;
③使用条件变量Condition 来实现等待唤醒,可以有多个条件变量,一种条件变量相当于monitor中的WaitSet;
为什么会有aqs的出现呢?在早期实现锁时一般都会使用一种同步器实现另一种同步器,因此后续jsr规范中提出aqs做统一的规范/提供统一的框架/模板,将实现锁的一些方法封装在里面,如果需要自定义锁则可以基于aqs做定制化,这也是一种模板方法模式。
自定义锁时需要重写的方法无非就是怎么获取锁怎么释放锁的操作,对应的就是对state的状态做什么样的改变。需要重写的钩子方法【一种被声明在抽象类中的方法,它可以是空方法(由子类实现),也可以是默认实现的方法】:
protected boolean tryAcquire(int arg); // 获取锁的操作【独占】protected boolean tryRelease(int arg); // 释放锁的操作【独占】protected int tryAcquireShared(int arg); // 获取锁的操作【共享】protected boolean tryReleaseShared(int arg); // 释放锁的操作【共享】protected boolean isHeldExclusively(); // 检查是否是独占锁
如果需要实现独占锁就重写独占型的方法,需要共享锁就重写共享型方法,当然也可以两种都实现【读写锁】。除了上述方法,aqs类中的其他方法都是final的,无法被重写。
2)自定义锁
如果我们要实现一个自定义锁,可以先实现Lock接口(MyLock),之后定义一个内部类继承AQS(MyAQS),这里的MyAQS为锁的实现者简化了锁的实现,MyLock为锁的使用者提供了与锁交互的接口。
/** 自定义AQS独占锁*/class MyLock implements Lock {/** 静态内部类继承aqs*/private static class MySync extends AbstractQueuedSynchronizer {/** 尝试获取锁的实现*/@Overrideprotected boolean tryAcquire(int arg) {if (compareAndSetState(0, 1)) {setExclusiveOwnerThread(Thread.currentThread());return true;}return false;}/** 尝试释放锁的实现*/@Overrideprotected boolean tryRelease(int arg) {if (Thread.currentThread() == getExclusiveOwnerThread()) {setExclusiveOwnerThread(null);setState(0);return true;} else {throw new IllegalMonitorStateException();}}/** 是否是独占持有锁*/@Overrideprotected boolean isHeldExclusively() {return getExclusiveOwnerThread() == Thread.currentThread();}/** 常见条件变量*/public Condition newCondition() {return new ConditionObject();}}private final MySync sync = new MySync();/** 使用静态内部类的方法来实现Lock接口中的方法*/@Overridepublic void lock() {sync.acquire(1);}@Overridepublic void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);}@Overridepublic boolean tryLock() {return sync.tryAcquire(1);}@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(time));}@Overridepublic void unlock() {sync.release(0);}@Overridepublic Condition newCondition() {return sync.newCondition();}}
3)ReentrantLock的原理
独占锁获取锁的过程:

