本文首發於一世流雲的專欄: https://segmentfault.com/blog...
ReentrantReadWriteLock類,顧名思義,是一種讀寫鎖,它是ReadWriteLock接口的直接實現,該類在內部實現了具體獨佔鎖特色的寫鎖,以及具備共享鎖特色的讀鎖,和ReentrantLock同樣,ReentrantReadWriteLock類也是經過定義內部類實現AQS框架的API來實現獨佔/共享的功能。segmentfault
ReentrantReadWriteLock類具備以下特色:安全
與ReadWriteLock類同樣,ReentrantReadWriteLock對象在構造時,能夠傳入參數指定是公平鎖仍是非公平鎖。併發
所謂鎖降級,就是:先獲取寫鎖,而後獲取讀鎖,最後釋放寫鎖,這樣寫鎖就降級成了讀鎖。可是,讀鎖不能升級到寫鎖。簡言之,就是:框架
寫鎖能夠降級成讀鎖,讀鎖不能升級成寫鎖。
ReentrantReadWriteLock的內部讀鎖類、寫鎖類實現了Lock接口,因此能夠經過newCondition()
方法獲取Condition對象。可是這裏要注意,讀鎖是無法獲取Condition對象的,讀鎖調用newCondition()
方法會直接拋出UnsupportedOperationException
。高併發
咱們知道,condition的做用實際上是對Object類的wait()
和notify()
的加強,是爲了讓線程在指定對象上等待,是一種線程之間進行協調的工具。
當線程調用condition對象的await
方法時,必須拿到和這個condition對象關聯的鎖。因爲線程對讀鎖的訪問是不受限制的(在寫鎖未被佔用的狀況下),那麼即便拿到了和讀鎖關聯的condition對象也是沒有意義的,由於讀線程以前不須要進行協調。
如下是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(); } } }
內部嵌套類聲明:
ReentrantReadWriteLock類有兩個內部嵌套類ReadLock
和WriteLock
,這兩個內部類的實例會在ReentrantReadWriteLock類的構造器中建立,並經過ReentrantReadWriteLock類的readLock()
和writeLock()
方法訪問。spa
ReadLock:線程
WriteLock:code
ReentrantReadWriteLock類的核心方法其實就兩個:readLock()
和writeLock()
,其它都是一些用來監控系統狀態的方法,返回的都是某一時刻點的近似值。對象