讀寫鎖ReentrantReadWriteLock性質

讀寫鎖ReentrantReadWriteLock性質

一、性質

1、支持鎖的降級,在寫鎖釋放前降級爲讀鎖
2、不支持鎖的升級,由讀鎖升級爲寫鎖將會失敗
3、寫鎖支持ReentrantLock.newCondition,讀鎖不支持,將會拋出異常UnsupportedOperationException

鎖的降級測試代碼

        System.out.println("Enter");
        r.lock();
        System.out.println("read lock ");
        r.unlock();
        w.lock();
        System.out.println("write lock");
        r.lock();
        System.out.println("read lock");
        w.unlock();
        r.unlock();
        System.out.println("Outer");

        /*output:
            Enter
            read lock 
            write lock
            read lock
            Outer
        */

鎖的升級測試代碼

        System.out.println("Enter");
        r.lock();
        System.out.println("read lock ");
        w.lock();//將會一直阻塞
        System.out.println("write lock");
        w.unlock();
        r.unlock();
        System.out.println("Outer");

        /*output:
            Enter
            read lock 
            程序一直阻塞
        */

二、使用場景

在讀多寫少的場景下,使用讀寫鎖提高程序的併發性 (實例代碼來源於jdk源碼註釋))

1、提供一個讀寫目錄,在讀數據時獲取讀鎖,寫數據時獲取寫鎖。只有讀線程訪問時,可以同時支持多個讀線程訪問,以此提供程序的併發性。

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(); }
   }
 }

2、系統緩存的更新,演示了鎖的升級和降級使用

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