Java ReentrantReadWriteLocks - how to safely acquire write lock?

前端 未结 12 1730
小蘑菇
小蘑菇 2020-11-28 19:00

I am using in my code at the moment a ReentrantReadWriteLock to synchronize access over a tree-like structure. This structure is large, and read by many threads at once wit

12条回答
  •  再見小時候
    2020-11-28 19:40

    Found in the documentation for ReentrantReadWriteLock. It clearly says, that reader threads will never succeed when trying to acquire a write lock. What you try to achieve is simply not supported. You must release the read lock before acquisition of the write lock. A downgrade is still possible.

    Reentrancy

    This lock allows both readers and writers to reacquire read or write locks in the style of a {@link ReentrantLock}. Non-reentrant readers are not allowed until all write locks held by the writing thread have been released.

    Additionally, a writer can acquire the read lock, but not vice-versa. Among other applications, reentrancy can be useful when write locks are held during calls or callbacks to methods that perform reads under read locks. If a reader tries to acquire the write lock it will never succeed.

    Sample usage from the above source:

     class CachedData {
       Object data;
       volatile boolean cacheValid;
       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();
            // 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();
            rwl.writeLock().unlock(); // Unlock write, still hold read
         }
    
         use(data);
         rwl.readLock().unlock();
       }
     }
    

提交回复
热议问题