Java多線程進階(四)—— J.U.C之locks框架:ReentrantReadWriteLock

b886e976d8d35e0a0332a37980ac74f8.jpeg

本文首發於一世流雲的專欄: https://segmentfault.com/blog...

1、ReentrantReadWriteLock類簡介

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

ReentrantReadWriteLock類具備以下特色:安全

1.1 支持公平/非公平策略

與ReadWriteLock類同樣,ReentrantReadWriteLock對象在構造時,能夠傳入參數指定是公平鎖仍是非公平鎖。
image.png併發

1.2 支持鎖重入

  • 同一讀線程在獲取了讀鎖後還能夠獲取讀鎖;
  • 同一寫線程在獲取了寫鎖以後既能夠再次獲取寫鎖又能夠獲取讀鎖;

1.3 支持鎖降級

所謂鎖降級,就是:先獲取寫鎖,而後獲取讀鎖,最後釋放寫鎖,這樣寫鎖就降級成了讀鎖。可是,讀鎖不能升級到寫鎖。簡言之,就是:框架

寫鎖能夠降級成讀鎖,讀鎖不能升級成寫鎖。

1.4 Condition條件支持

ReentrantReadWriteLock的內部讀鎖類、寫鎖類實現了Lock接口,因此能夠經過newCondition()方法獲取Condition對象。可是這裏要注意,讀鎖是無法獲取Condition對象的,讀鎖調用newCondition() 方法會直接拋出UnsupportedOperationException高併發

咱們知道,condition的做用實際上是對Object類的 wait()notify()的加強,是爲了讓線程在指定對象上等待,是一種線程之間進行協調的工具。
當線程調用condition對象的 await方法時,必須拿到和這個condition對象關聯的鎖。因爲線程對讀鎖的訪問是不受限制的(在寫鎖未被佔用的狀況下),那麼即便拿到了和讀鎖關聯的condition對象也是沒有意義的,由於讀線程以前不須要進行協調。

1.5 使用示例

如下是Oracle官方給出的一個例子:
使用ReentrantReadWriteLock控制對TreeMap的訪問(利用讀鎖控制讀操做的訪問,利用寫鎖控制修改操做的訪問),將TreeMap包裝成一個線程安全的集合,而且利用了讀寫鎖的特性來提升併發訪問。工具

public class RWTreeMap {
    private final Map<String, Data> m = new TreeMap<String, Data>();
    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    private final Lock r = rwl.readLock();
    private final Lock w = rwl.writeLock();
 
    public Data get(String key) {
        r.lock();
        try {
            return m.get(key);
        } finally {
            r.unlock();
        }
    }
 
    public String[] allKeys() {
        r.lock();
        try {
            return (String[]) m.keySet().toArray();
        } finally {
            r.unlock();
        }
    }
 
    public Data put(String key, Data value) {
        w.lock();
        try {
            return m.put(key, value);
        } finally {
            w.unlock();
        }
    }
 
    public void clear() {
        w.lock();
        try {
            m.clear();
        } finally {
            w.unlock();
        }
    }
}

2、ReentrantReadWriteLock類/方法聲明

2.1 類聲明

image.png

內部嵌套類聲明:
ReentrantReadWriteLock類有兩個內部嵌套類ReadLockWriteLock,這兩個內部類的實例會在ReentrantReadWriteLock類的構造器中建立,並經過ReentrantReadWriteLock類的readLock()writeLock()方法訪問。spa

ReadLock:
image.png線程

WriteLock:
image.pngcode

2.2 方法聲明

ReentrantReadWriteLock類的核心方法其實就兩個:readLock()writeLock(),其它都是一些用來監控系統狀態的方法,返回的都是某一時刻點的近似值。對象

image.png

相關文章
相關標籤/搜索