上一片学习了Lock顶级接口,现在学习一下队列同步器AbstractQueuedSynchronizer,也就是网上常看到AQS。
AbstractQueuedSynchronizer
目前我看到的Lock的实现最终都是通过AQS同步器来实现同步,所以了解这个类对了解Lock的实现有很大的帮助。
这个类提供了很多方法:
根据源码注释,非常容易理解到,这个类提供了和lock类似功能的方法。
比如这一组方法(独占锁):
- acquire(int) 获取锁
- acquireInterruptibly(int) 获取锁并响应中断
- tryAcquireNanos(int, long) 持续一段时间获取锁,获取到返回true,获取不到或者超时返回false
- release(int) 释放锁
还有一组(共享锁):
- acquireShared(int) 获取锁
- acquireSharedInterruptibly(int) 获取锁并响应中断
- tryAcquireSharedNanos(int, long) 持续一段时间获取锁,获取到返回true,获取不到或者超时返回false
- releaseShared(int) 释放锁
ps:独占锁和共享锁,后面再详细了解
唯一和Lock接口有区别的是获取锁和释放锁的调用,多了一个int参数,这个参数的意义是什么?
源码注释:
arg the acquire argument. This value is conveyed to
* {@link #tryAcquire} but is otherwise uninterpreted and
* can represent anything you like
注释上说这个参数是给tryAcquire方法使用的,可以代表你喜欢的任何东西。
可以还是无法理解这个参数的意义,希望以后了解的多了,能够理解这个参数,当然如果有大神看到我这篇了解AQS的博客,能在评论里指点一下。
基本使用
这个类是一个抽象类,抽象类是没法直接使用的,所以注释里给了最常用的使用方式。
常用使用方式:
public class Mutex implements Lock{
private static class Sync extends AbstractQueuedLongSynchronizer {
@Override
protected boolean tryAcquire (long arg) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease (long arg) {
if (getState() == 0) {
throw new IllegalMonitorStateException();
} else {
setExclusiveOwnerThread(null);
}
setState(0);
return true;
}
@Override
protected boolean isHeldExclusively () {
return getState() == 1;
}
Condition newCondition() {
return new ConditionObject();
}
}
private final Sync sync = new Sync();
@Override
public void lock () {
sync.acquire(1);
}
@Override
public void lockInterruptibly () throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock (long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(time));
}
@Override
public boolean tryLock () {
return sync.tryAcquire(1);
}
@Override
public void unlock () {
sync.tryRelease(1);
}
@Override
public Condition newCondition () {
return sync.newCondition();
}
}
在常用的使用方式中,类实现了Lock接口,类中有一个内部类继承了AQS,把操作锁的方法都委托给了内部类来实现。
比如最常用的ReentranLock就是这种实现方式。
网上有很多关于AQS的实现原理的,都是很好的文章,以后有需要再看。