聊聊你對AQS的瞭解

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已經加完鎖後,另外的線程再想加鎖就將一個隊列中等待鎖的釋放。

除此之外,該鎖的還支持獲取鎖時的公平和非公平性選擇。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章