AQS(AbstractQueuedSynchronizer)是java.util.concurrent包中的一个基础类,很多并发的工具类都是利用他进行的开发,比如ReetrantLock、Semphore、线程池等等。所以在这里我把AQS的源码进行了整理和阅读,这只是理解整个juc包的一个基础,要想掌握AQS,还需要通过和他的实现类相结合来理解,这篇文章算是本人学习jdk并发源码的第一篇学习笔记,当中理解有错的地方还请大家指正,谢谢。以下的源码都是基于JDK1.8的。
AQS本身是一个抽象类(但是没有抽象方法),他提供了以下几个模板方法供子类实现,从而让子类利用AQS来实现自己的锁机制。这几个方法不设为抽象方法,是为了如果子类只使用独占和共享模式中的一个模式,不需要把所有方法都实现。
//模板方法,用于独占模式获取锁
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
//模板方法,用于独占模式释放锁
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
//共享模式下尝试获取锁。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
//共享模式下释放锁,如果释放后允许唤醒后续等待结点返回true,否则false。
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
//表示在独占模式下,当前线程是否持有锁
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
1.类的说明
在jdk中说明摘抄这个类的作用如下
为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关同步器(信号量、事件,等等)提供一个框架。此类的设计目标是成为依靠单个原子 int 值来表示状态的大多数同步器的一个有用基础(private volatile int state)。子类必须定义更改此状态的受保护方法(也就是上面几个模板方法),并定义哪种状态对于此对象意味着被获取或被释放。假定这些条件之后,此类中的其他方法就可以实现所有排队和阻塞机制。子类可以维护其他状态字段,但只是为了获得同步而只追踪使用 getState()
、setState(int)
和 compareAndSetState(int, int)
方法来操作以原子方式更新的 int 值。
说明中建议,子类应该使用非public的内部类来实现外部类的同步属性,一般源码中都是定义一个内部类Sync来继承。具体的实现我们后面的日记再说。
此类支持独占模式(默认的)和共享模式,在共享模式下成功获取某一锁时,下一个等待线程(如果存在)也必须确定自己是否可以成功获取该锁。ReadWriteLock就实现了两种模式。
AQS定义了一个嵌套类(ConditionObject),子类可以用它来实现Coindition,这个类用于支持独占模式。
2.官方案例,jdk注释中给了两个官方用AQS实现锁的例子
2.1
这是一个不可重入的独占锁,使用了0来表示无锁的状态,1来表示锁定状态, 非重入锁不需要严格的记录当前锁的拥有者线程,这个类依然做了记录使得易于监控。
class Mutex implements Lock, java.io.Serializable {
// Our internal helper class
private static class Sync extends AbstractQueuedSynchronizer {
// Report whether in locked state
protected boolean isHeldExclusively() {
return getState() == 1; //如果state状态为1,代表当前当前线程拥有锁
}
// Acquire the lock if state is zero在state为0是尝试获取锁,获取锁失败直接返回false
public boolean tryAcquire(int acquires) {
assert acquires == 1; // Otherwise unused
if (compareAndSetState(0, 1)) {//检查是否能够把状态由0改成1
setExclusiveOwnerThread(Thread.currentThread());//获取锁成功,当前线程设置为拥有锁线程
return true;
}
return false;
}
// Release the lock by setting state to zero通过设置state为0来释放锁。
protected boolean tryRelease(int releases) {
assert releases == 1; // Otherwise unused
if (getState() == 0) throw new IllegalMonitorStateException();//state为0,这证明已经被释放
setExclusiveOwnerThread(null);//将拥有锁线程设置为null
setState(0);//将state设置为0
return true;
}
// Provide a Condition 提供了一个condition,具体操作后面会讲
Condition newCondition() { return new ConditionObject(); }
// Deserialize properly
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
// The sync object does all the hard work. We just forward to it
private final Sync sync = new Sync();
//通过调用内部类Sync的方法来实现锁。
public void lock() { sync.acquire(1); }
public boolean tryLock() { return sync.tryAcquire(1); }
public void unlock() { sync.release(1); }
public Condition newCondition() { return sync.newCondition(); }
public boolean isLocked() { return sync.isHeldExclusively(); }
public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }//查看是否有其他线程正在等待这个锁
public void lockInterruptibly() throws InterruptedException { //试图获取锁,如果当前线程被中断则终止
sync.acquireInterruptibly(1);
}
public boolean tryLock(long timeout, TimeUnit unit) //试图在指定时间内获取锁
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
}
2.2
这是一个类似于CountDownLatch的latch类,除了它值需要单个signal来触发。因为一个latch锁并不是独占锁,它使用shared模式的acquire和release方法。state为1表示释放了锁
class BooleanLatch {
private static class Sync extends AbstractQueuedSynchronizer {
boolean isSignalled() { return getState() != 0; }//状态不为0表示已经锁已经被singalled(释放时把state置为1)
//重写共享模式的获取锁方法,如果state大于0则返回1,表示获取锁成功,state为0则表示不能获取锁
protected int tryAcquireShared(int ignore) {
return isSignalled()? 1 : -1;//因为只能单个共享,所以只有被Signalled了的状态才能再次获取锁成功
}
protected boolean tryReleaseShared(int ignore) {
setState(1);//释放锁,把state设置为1。
return true;
}
}
private final Sync sync = new Sync();
public boolean isSignalled() { return sync.isSignalled(); }
public void signal() { sync.releaseShared(1); }//共享模式signal,调用了tryReleaseShared方法,然后释放
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);//如果线程被中断就中止,否则调用了tryAcquireShared。如果
//获取锁失败,则park自己(具体过程看后面的源码解析)
}
}
以上就是AQS的一个基本概念,下面一篇就是关于AQS的具体源码分析了。