AQS主要用来构建锁或者其他同步器组件的基础框架,它使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成想获取资源的线程的排队工作。其主要使用方式是继承,子类通过继承它并实现它的抽象方法来管理同步状态,在管理同步状态的时候就需要对同步状态变量(int成员变量)进行修改,为了安全的修改同步状态变量就可以使用AQS已经提供的三个方法(getState()
,setState(int newState)
,compareAndSetState(int expect, int update)
)修改。AQS的子类被推荐定义为自定义同步组件的静态内部类,同步器自身没有实现任何同步接口,可以支持共享式地获取同步状态,可以方便实现不同的同步组件(ReentrantLock,ReentrantReadWriteLock和CountDownLatch等)。
自定义的同步组件(如锁)是面向使用者的,使用者无需关心内部实现,而AQS面向同步组件的实现者的,简化组件的实现方式。
state
为0代表没有线程占有锁,可以去抢这个锁,用CAS
设置state
为非0,如果CAS
成功说明抢到锁了,如果是可重入的话则state
可以加1。
state
非0代表有线程占有锁,解锁减去1直到state
等于0代表释放锁。
getState()
: 获取当前的同步状态setState()
: 设置当前的同步状态compareAndSetState(int expect, int update)
: 使用CAS
设置当前状态,该方法能够保证状态设置的原子性。CAS
设置同步状态。执行acquire
方法的线程会调用此方法,如果此方法失败,则acquire
方法可能会将线程排队(如果尚未排队),直到其他线程发出释放信号。这可以用来实现方法Lock.tryLock()
|
| protected boolean tryRelease(int arg) | 通过尝试修改同步状态变量以释放同步状态,执行release方法的线程会调用这个方法,等待获取同步状态的线程有机会获取同步状态。 |
| protected int tryAcquireShared(int arg) | 以共享的方式获取同步状态,此方法应该查询当前状态是否允许以共享模式去获取它,返回大于等于0的值,表示获取成功,反之,获取失败。 |
| protected boolean tryReleaseShared(int arg) | 以共享的方式释放同步状态 |
| protected boolean isHeldExclusively() | 当前同步器是否在独占模式下被当前线程占用,即表示是否被当前线程所独占。 |
上面方法不重写的话默认实现是抛出UnsupportedOperationException
异常
class Mutex implements Lock, java.io.Serializable {
// 静态内部类
// Our internal helper class
private static class Sync extends AbstractQueuedSynchronizer {
// Reports whether in locked state
// 判断是否处于占用状态
protected boolean isHeldExclusively() {
return getState() == 1;
}
// Acquires the lock if state is zero
public boolean tryAcquire(int acquires) {
assert acquires == 1; // Otherwise unused
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread()); //AQS中已定义的方法,设置当前拥有独占访问权限的是哪个线程
return true;
}
return false;
}
// Releases the lock by setting state to zero
protected boolean tryRelease(int releases) {
assert releases == 1; // Otherwise unused
if (getState() == 0) throw new IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
// Provides a Condition
Condition newCondition() {
return new ConditionObject();
}
// Deserializes properly
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
// 使用Sync完成相关的同步操作
// The sync object does all the hard work. We just forward to it.
private final Sync sync = new 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));
}
}