https://blog.csdn.net/AAA821/article/details/79712522这篇博客介绍了一下AQS
然后看了下阿里Druid的源码,举其中一个方法来解释AQS的作用,通过例子可以更好的理解AQS的作用
这个是SimpleCanalConnector的connect方法,
public void connect() throws CanalClientException {
if (connected) {
return;
}
if (runningMonitor != null) {
if (!runningMonitor.isStart()) {
runningMonitor.start();
}
} else {
waitClientRunning();//这里调用了Sync
doConnect();
if (filter != null) {
subscribe(filter);
}
if (rollbackOnConnect) {
rollback();
}
}
connected = true;
}
private void waitClientRunning() {
try {
if (zkClientx != null) {
if (!connected) {// 未调用connect
throw new CanalClientException("should connect first");
}
mutex.get();// 阻塞等待 mutex = BooleanMutex
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new CanalClientException(e);
}
}
下面是BooleanMutex的get()方法
/**
* 阻塞等待Boolean为true
*
* @throws InterruptedException
*/
public void get() throws InterruptedException {
sync.innerGet(); //sync = Sync
}
下面是Sync的innerGet()方法
void innerGet() throws InterruptedException {
acquireSharedInterruptibly(0);
}
下面是AbstractQueuedSynchronizer的acquireSharedInterruptibly
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
这个方法链的调用,就是在连接前,调用AbstractQueuedSynchronizer的acquireSharedInterruptibly方法,先判断能不用获取到锁(tryAcquireShared 尝试获取共享锁)
1.如果能够获取到锁,则我这个线程就不用阻塞
2.如果获取不到锁,则调用doAcquireSharedInterruptibly方法将线程封装到Node存放到Queue里去,等待获取锁的线程释放锁,才会唤醒你,结束你的阻塞
为什么连接方法就要用到AQS,无非就是想控制并发