AQS是一個併發包的基礎組件,用來實現各種鎖,各種同步組件的。
包含了state變量、加鎖線程、等待隊列等併發中的核心組件。
AQS全稱是隊列同步器AbstractQueuedSynchronizer,是用來構建鎖或者其他同步組件的基礎框架。
它使用了一個int成員變量表示同步狀態,默認情況下是0
/**
- The synchronization state.
*/
private volatile int state;
通過內置的FIFO隊列來完成資源獲取線程的排隊工作。
同步器的主要使用方式是繼承,子類通過繼承同步器並實現它的抽象方法來管理同步狀態,在抽象方法的實現過程中免不了要對同步狀態進行更改。
這時就需要使用同步器提供的3個方法(getState()、setState(int newState)和compareAndSetState(int expect,int update))來進行操作,因爲它們能夠保證狀態的改變是安全的。
/**獲取當前同步狀態
protected final int getState() {
return state;
}
/**
設置當前同步狀態
*/
protected final void setState(int newState) {
state = newState;
}
```java
/**
使用CAS設置當前狀態,該方法能夠保證狀態設置的原子性。
*/
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
同步器既可以支持獨佔式地獲取同步狀態,也可以支持共享式地獲取同步狀態,這樣就可以方便實現不同類型的同步組件(ReentrantLock、ReentrantReadWriteLock和CountDownLatch)。
獨佔鎖就是在同一時刻只能有一個線程獲取到鎖,而其他獲取鎖的線程只能處於同步隊列中等待,只有獲取鎖的線程釋放了鎖,後繼的線程才能夠獲取鎖。
示例代碼
class Mutex implements Lock {
// 靜態內部類,自定義同步器
private static class Sync extends AbstractQueuedSynchronizer {
// 是否處於佔用狀態
protected boolean isHeldExclusively() {
return getState() == 1;
}
// 當狀態爲0的時候獲取鎖
public boolean tryAcquire(int acquires) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
// 釋放鎖,將狀態設置爲0
protected boolean tryRelease(int releases) {
if (getState() == 0) throw new
IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
// 返回一個Condition,每個condition都包含了一個condition隊列
Condition newCondition() { return new ConditionObject(); }
}
// 僅需要將操作代理到Sync上即可
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));
}
在tryAcquire(int acquires)方法中,如果經過CAS設置成功(同步狀態設置爲1),則代表獲
取了同步狀態,而在tryRelease(int releases)方法中只是將同步狀態重置爲0。
可重入鎖ReentrantLock和AQS的關係
顧名思義,就是支持重進入的鎖,它表示該鎖能夠支持一個線程對資源的重複加鎖。
ReentrantLock內部也是包含了一個AQS對象。
abstract static class Sync extends AbstractQueuedSynchronizer {
...
}
從這裏理解等待隊列,當線程1已經加完鎖後,另外的線程再想加鎖就將一個隊列中等待鎖的釋放。
除此之外,該鎖的還支持獲取鎖時的公平和非公平性選擇。