ReentrantReadWriteLock 類

ReentrantReadWriteLock 類, 顧名思義, 是一種讀寫鎖, 它是 ReadWriteLock 接口的直接實現, 該類在內部實現了具體獨佔鎖特點的寫鎖, 以及具有共享鎖特點的讀鎖, 和 ReentrantLock 一樣, ReentrantReadWriteLock 類也是通過定義內部類實現AQS框架的API來實現獨佔/共享的功能.

ReentrantLock 屬於排他鎖, 這些鎖在同一時刻只允許一個線程進行訪問, 但是在大多數場景下, 大部分時間都是提供讀服務, 而寫服務佔有的時間較少. 而且, 讀服務不存在數據競爭問題, 如果一個線程在讀時禁止其他線程讀勢必會導致性能降低. 所以就提供了讀寫鎖.

讀寫鎖維護着一對鎖, 一個讀鎖和一個寫鎖. 通過分離讀鎖和寫鎖, 使得併發性比一般的排他鎖有了較大的提升:

  • 在同一時間, 可以允許多個讀線程同時訪問.
  • 但是, 在寫線程訪問時, 所有讀線程和寫線程都會被阻塞.

讀寫鎖的主要特性:

  • 公平性:支持公平性和非公平性.
  • 重入性:支持重入. 讀寫鎖最多支持 65535 個遞歸寫入鎖和 65535 個遞歸讀取鎖.
  • 鎖降級:遵循獲取寫鎖, 再獲取讀鎖, 最後釋放寫鎖的次序, 如此寫鎖能夠降級成爲讀鎖.

ReadWriteLock

讀寫鎖 ReentrantReadWriteLock 實現接口 ReadWriteLock, 該接口維護了一對相關的鎖, 一個用於只讀操作, 另一個用於寫入操作. 只要沒有 writer, 讀取鎖可以由多個 reader 線程同時保持. 寫入鎖是獨佔的.

public interface ReadWriteLock {
    Lock readLock();
    Lock writeLock();
}

ReadWriteLock 定義了兩個方法. readLock() 返回用於讀操作的鎖, writeLock() 返回用於寫操作的鎖.

ReentrantReadWriteLock

java.util.concurrent.locks.ReentrantReadWriteLock 定義如下.

/** 內部類  讀鎖 */
private final ReentrantReadWriteLock.ReadLock readerLock;
/** 內部類  寫鎖 */
private final ReentrantReadWriteLock.WriteLock writerLock;

final Sync sync;

/** 使用默認(非公平)的排序屬性創建一個新的 ReentrantReadWriteLock */
public ReentrantReadWriteLock() {
    this(false);
}

/** 使用給定的公平策略創建一個新的 ReentrantReadWriteLock */
public ReentrantReadWriteLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
    readerLock = new ReadLock(this);
    writerLock = new WriteLock(this);
}

/** 返回用於寫入操作的鎖 */
@Override
public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
/** 返回用於讀取操作的鎖 */
@Override
public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }

abstract static class Sync extends AbstractQueuedSynchronizer {
    /**
     * 省略其餘源代碼
     */
}
public static class WriteLock implements Lock, java.io.Serializable {
    /**
     * 省略其餘源代碼
     */
}

public static class ReadLock implements Lock, java.io.Serializable {
    /**
     * 省略其餘源代碼
     */
}

ReentrantReadWriteLockReentrantLock 一樣, 其鎖主體依然是 Sync, 它的讀鎖、寫鎖都是依靠 Sync 來實現的.

所以 ReentrantReadWriteLock 實際上只有一個鎖, 只是在獲取讀取鎖和寫入鎖的方式上不一樣而已, 它的讀寫鎖其實就是兩個類: ReadLockwriteLock, 這兩個類都是lock實現.

ReentrantLock 中, 使用 Sync ( 實際是 AQS ) 的 int 類型的 state 來表示同步狀態, 表示鎖被一個線程重複獲取的次數.

但是, 讀寫鎖 ReentrantReadWriteLock 內部維護着一對讀寫鎖, 如果要用一個變量維護多種狀態, 需要採用 “按位切割使用” 的方式來維護這個變量, 將其切分爲兩部分: 高16爲表示讀, 低16爲表示寫.

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