AQS是一个Java提供的底层同步工具类,用一个volatile int state的变量表示同步状态(代表共享资源),并提供了一系列的CAS操作来管理这个同步状态,同时还维护着一个FIFO线程同步队列(双向队列,多线程争用资源被阻塞时会进入此队列,使用unsafe进行线程的等待与唤醒)。
AQS的主要作用是为Java中的并发同步组件提供统一的底层支持,如常用的ReentrantLock,Semaphore,CountDownLatch等等就是基于AQS实现的,用法是通过继承AQS实现其模版方法,然后将子类作为同步组件的内部类。
state的访问方式有三种:
- getState()
- setState()
- compareAndSetState()
AQS定义两种资源共享方式:
- Exclusive(独占,只有一个线程能执行,如ReentrantLock)
- Share(共享,多个线程可同时执行,如Semaphore/CountDownLatch)
自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可,自定义同步器实现时主要实现以下几种方法:
- isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
- tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
- tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
- tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
- tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。
独占锁的示例
/**
* 实现一个独占锁
*/
public class Mutex implements Lock {
private static class Sync extends AbstractQueuedSynchronizer{
//是否是独占
protected boolean isHeldExclusively(){
return getState() == 1;
}
//独占式只支持1个acquires
public boolean tryAcquire(int acquires){
if(compareAndSetState(0,1)){
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
//释放锁
protected boolean tryRelease(int release){
if(getState() == 0){
throw new IllegalMonitorStateException();
}
setExclusiveOwnerThread(null);
setState(0);
return true;
}
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() {
return sync.tryAcquire(1);
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1,unit.toNanos(time));
}
@Override
public void unlock() {
sync.release(1);
}
@Override
public Condition newCondition() {
return sync.newCondition();
}
//是否是独占锁
public boolean isLock(){
return sync.isHeldExclusively();
}
public boolean hasQueuedThreads(){
return sync.hasQueuedThreads();
}
}
示例中通过实现Lock接口,然后使用一个内部类继承AbstractQueuedSynchronizer来实现一个独占锁。
共享锁示例
/**
* 共享锁示例
*/
public class SharedLockInstance implements Lock {
private final Sync sync = new Sync(2);
public LockInstance() throws IllegalAccessException {
}
//内部类继承AbstractQueuedSynchronizer
private static final class Sync extends AbstractQueuedSynchronizer{
Sync(int state) throws IllegalAccessException {
if(state <= 0){
throw new IllegalAccessException("count must large than 0");
}
setState(state);
}
@Override
public int tryAcquireShared(int arg){
for(;;){
System.out.println("try acquire...");
int current = getState();
int now = current - arg;
if(now < 0 || compareAndSetState(current,now)){
return now;
}
}
}
@Override
public boolean tryReleaseShared(int arg){
for(;;){
System.out.println("try release...");
int current = getState();
int now = current + arg;
if(compareAndSetState(current,now)){
return true;
}
}
}
Condition newCondition(){
return new ConditionObject();
}
}
@Override
public void lock() {
sync.acquireShared(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return sync.tryAcquireShared(1) >= 0;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireSharedNanos(1,unit.toNanos(time));
}
@Override
public void unlock() {
sync.tryReleaseShared(1);
}
@Override
public Condition newCondition() {
return sync.newCondition();
}
}
不论是独占式锁还是共享锁都是在通过继承了AQS里的模板方法,这些模板方法大致分3类:独占式获取与释放同步状态,共享式获取与释放同步状态和查询同步队列中的等待线程情况。
一般来说,自定义同步器要么是独占方法,要么是共享方式,他们也只需实现tryAcquire-tryRelease、tryAcquireShared-tryReleaseShared中的一种即可。但AQS也支持自定义同步器同时实现独占和共享两种方式,如ReentrantReadWriteLock。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。