一、定义
AQS全称是:AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架。框架可理解为所有工具类均要继承/实现该父类才可使用。
特点:
用state属性来表示资源的状态(独占模式或共享模式),子类需要定义如何维护此状态,控制如何获取锁和释放锁;
- getState:获取 state 状态;<br /> - setState:设置 state 状态;<br /> - compareAndSetState :cas机制设置 state 状态。注意AQS本身是阻塞式锁,只是设置state状态时采用了cas,防止多线程同时设置state,保证线程安全;<br /> - 独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源;
提供了基于FIFO的等待队列,类似Monitor的EntryList;
- 使用条件变量来实现等待、唤醒机制,支持多个条件变量,类似于Monitor的WaitSet;
 
子类主要实现这样一些方法(默认抛出UnsupportedOperationException)
- tryAcquire
 - tryRelease
 - tryAcquireShared
 - tryReleaseShared
 - isHeldExclusively
 
获取锁的姿势(模板):
//如果获取锁失败if(!tryAcquire(arg)){//入队,可以选择阻塞当前线程}
释放锁的姿势(模板):
//如果释放锁成功if(tryRelease(arg)){//让阻塞线程恢复运行}
二、应用
使用AQS实现自定义锁(不可重入锁)
import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.AbstractQueuedSynchronizer;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;public class TestAQS {}class MyLock implements Lock{//创建内部类,使用AQS创建锁class MySync extends AbstractQueuedSynchronizer{@Overrideprotected boolean tryAcquire(int arg) {//cas保证操作原子性,根本上解决了线程安全问题if(compareAndSetState(0,1)){//加锁成功,设置锁的owner为当前线程setExclusiveOwnerThread(Thread.currentThread());}}@Overrideprotected boolean tryRelease(int arg) {//取消锁的持有者,设置持有锁的线程==nullsetExclusiveOwnerThread(null);//设置状态为0setState(0);return true;}@Overrideprotected boolean isHeldExclusively() {//注意这里是在判断独占锁是否被持有,而不是在判断独占锁是否被当前线程持有return getState()==1;}protected Condition newCondition(){return new ConditionObject();}}MySync mySync = new MySync();@Override //加锁,不成功会进入等待队列public void lock() {//这里调用了AQS中自带的方法,acquire是当无法获取锁时,线程进入阻塞队列等待锁,tryAcquire方法是获取不到锁则不再获取,只一次;mySync.acquire(1);}@Override //加锁,可打断public void lockInterruptibly() throws InterruptedException {mySync.acquireSharedInterruptibly(1);}@Override //尝试加锁(一次)public boolean tryLock() {return false;}@Override //尝试加锁(带超时)public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {return mySync.tryAcquireNanos(1, unit.toNanos(time));}@Override //解锁public void unlock() {mySync.release(1);/** release在释放锁后会唤醒阻塞队列中等待锁的线程* 而tryRelease在释放锁会并不会唤醒线程* */}@Override //创建条件变量public Condition newCondition() {return mySync.newCondition();}}
本例中,AQS的使用较为清晰。AQS可理解为一种将锁包装起来的工具类,以往线程获取锁需要先创建某一对象,然后在对象上加锁再获取锁。AQS相当于创建获得锁、释放锁等接口,将实现细节(如synchronized语句块)封装,只暴露接口给外部,以供调用。这个思想和ReentrantLock类似,ReentrantLock的实现是调用lock()与unlock()思想,也体现了封装的思想。
类中state属性用来表示锁是否被持有。一般state=0表示锁未被持有,state>0表示锁被持有;
AQS是一种阻塞式锁(悲观锁),这是由其内部实现的。具体表现为AQS的acquire方法:尝试获取锁,当无法获取锁时则会进入阻塞队列等待锁释放。
与ReenTrantLock使用方法类似,线程首先加锁、在try中实现需要加锁的代码,并在finally块中解锁;
本例中的自定义锁还是一种不可重入锁,因为lock方法调用AQS的tryAcquire方法,而tryAcquire方法的实现细节即为:cas试图将state从0改为1,可以防止锁重入
import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.AbstractQueuedSynchronizer;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;public class TestAQS {public static void main(String[] args) {MyLock myLock = new MyLock();new Thread(()->{myLock.lock();try {System.out.println("locking...");Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} finally {myLock.unlock();}},"t1").start();new Thread(()->{myLock.lock();try {System.out.println("locking...");Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} finally {myLock.unlock();}},"t2").start();}}class MyLock implements Lock{//创建内部类,使用AQS创建锁class MySync extends AbstractQueuedSynchronizer{@Overrideprotected boolean tryAcquire(int arg) {//cas保证操作原子性,根本上解决了线程安全问题if(compareAndSetState(0,1)){//加锁成功,设置锁的owner为当前线程setExclusiveOwnerThread(Thread.currentThread());return true;}return false;}@Overrideprotected boolean tryRelease(int arg) {//取消锁的持有者,设置持有锁的线程==nullsetExclusiveOwnerThread(null);//设置状态为0setState(0);return true;}@Overrideprotected boolean isHeldExclusively() {//注意这里是在判断独占锁是否被持有,而不是在判断独占锁是否被当前线程持有return getState()==1;}protected Condition newCondition(){return new ConditionObject();}}MySync mySync = new MySync();@Override //加锁,不成功会进入等待队列public void lock() {//这里调用了AQS中自带的方法,acquire是当无法获取锁时,线程进入阻塞队列等待锁,tryAcquire方法是获取不到锁则不再获取,只一次;mySync.acquire(1);}@Override //加锁,可打断public void lockInterruptibly() throws InterruptedException {mySync.acquireSharedInterruptibly(1);}@Override //尝试加锁(一次)public boolean tryLock() {return false;}@Override //尝试加锁(带超时)public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {return mySync.tryAcquireNanos(1, unit.toNanos(time));}@Override //解锁public void unlock() {mySync.release(1);/** release在释放锁后会唤醒阻塞队列中等待锁的线程* 而tryRelease在释放锁会并不会唤醒线程* */}@Override //创建条件变量public Condition newCondition() {return mySync.newCondition();}}
