ReentrantReadWriteLock與ReentrantLock對比分析

一.前言

ReentrantReadWriteLock與ReentrantLockde的關係並不是雷峯塔與雷鋒的關係。

個人理解:
synchronized ——> ReentrantLock ——> ReentrantReadWriteLock是JVM逐漸向程序員放權的過程。

synchronized是將線程管理的操作全部交給了JVM,開發人員不需要關心線程的鎖、線程切換等細節,反正在方法上或類上加上這個關鍵字就線程安全了。但是JVM對synchronized的實現並不高效,例如:synchronized是採用公平鎖,操作會排一個隊按順序執行,來保證執行順序。(會消耗更多的時間來排隊)
而不公平情況下,是無序狀態允許插隊,jvm會自動計算如何處理更快速來調度插隊。(如果不關心順序,這個速度會更快)

ReentrantLock是synchronized的一個改進,他將更多的權利交給了開發人員,他允許開發人員對線程做更細粒度的操作,直接操作鎖。

ReentrantReadWriteLock是ReentrantLock的進一步改進,他將鎖更細分爲讀鎖和寫鎖,粒度更細。

二.ReentrantReadWriteLock的使用原則

總則:ReentrantReadWriteLock分爲讀鎖和寫鎖,多個讀鎖不互斥,讀鎖與寫鎖互斥。如果你的代碼只讀數據,可以很多人同時讀,但不能同時寫,那就上讀鎖;如果你的代碼修改數據,只能有一個人在寫,且不能同時讀取,那就上寫鎖。總之,讀的時候上讀鎖,寫的時候上寫鎖!

(a).重入方面其內部的WriteLock可以獲取ReadLock,但是反過來ReadLock想要獲得WriteLock則永遠都不要想。

(b).WriteLock可以降級爲ReadLock,順序是:先獲得WriteLock再獲得ReadLock,然後釋放WriteLock,這時候線程將保持Readlock的持有。反過來ReadLock想要升級爲WriteLock則不可能。

(c).ReadLock可以被多個線程持有並且在作用時排斥任何的WriteLock,而WriteLock則是完全的互斥。這一特性最爲重要,因爲對於高讀取頻率而相對較低寫入的數據結構,使用此類鎖同步機制則可以提高併發量。

(d).不管是ReadLock還是WriteLock都支持Interrupt,語義與ReentrantLock一致。

(e).WriteLock支持Condition並且與ReentrantLock語義一致,而ReadLock則不能使用Condition,否則拋出UnsupportedOperationException異常。

三.使用示例

 class CachedData {
   Object data;
   volatile boolean cacheValid;
   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

   void processCachedData() {
     rwl.readLock().lock();
     if (!cacheValid) {
        // Must release read lock before acquiring write lock
        rwl.readLock().unlock();
        rwl.writeLock().lock();
        try {
          // Recheck state because another thread might have
          // acquired write lock and changed state before we did.
          if (!cacheValid) {
            data = ...
            cacheValid = true;
          }
          // Downgrade by acquiring read lock before releasing write lock
          rwl.readLock().lock();
        } finally {
          rwl.writeLock().unlock(); // Unlock write, still hold read
        }
     }

     try {
       use(data);
     } finally {
       rwl.readLock().unlock();
     }
   }
 }
class RWDictionary {
    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 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(); }
    }
 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章