AQS(AbstractQueuedSynchronizer)是各种锁实现的基础,提供了对资源(state字段)的获取与阻塞等待,阻塞的线程会被放进一个先进先出(FIFO)的同步队列里。各种锁是AQS的子类,子类必须实现一套用来改变state变量(volatile 修饰的变量)的方法,包括锁资源的获取方法与锁资源的释放方法。始终记得:volitile和cas操作铸就了AQS的辉煌。
众所周知,锁分排他锁和共享锁, AQS对锁的获取与释放也是分两种情况的,即SHARED与EXCLUSIVE两种模式。即如下图代码:
EXCLUSIVE模式的锁必须实现tryAcquire和tryRelease两个抽象方法,同理,SHARED模式的锁必须实现tryAcquireShared和tryReleaseShared两个抽象方法。至于为什么AQS是个抽象类而不是接口的原因就在于次,比如你只需要排他锁就只用实现你需要的那两个方法,而不需要像接口那样需要实现全部抽象方法。当然也有同时实现两套方法的锁,如ReadWriteLock.
state资源
state字段是AQS锁的核心,即是锁资源,该字段是volatile修饰的。volatile主要对所修饰的变量提供两个功能:①可见性②防止指令重排序。AQS框架都是对state变量的CAS增减操作,不通的增减方式从而实现了不同性质的锁,例如重入锁在同对象再次重入该锁锁住的资源时候,会对state字段进行加一操作。操作state字段有三个方法:
getState()
setState()
compareAndSetState()
这三个均是原子操作,compareAndSetState的实现依赖于Unsafe的compareAndSwapInt()方法,即
自定义锁方法
如刚才介绍,有两种锁,有两套方法。每次自定义锁实现的时候需要自己去实现自己需要的方法。默认情况下不重写的方法返回抛出UnsupportedOperationException异常。以下是需要重写的方法:
isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。