Why readLock () must be unlocked before writeLock () in ReentrantReadWriteLock. Lock ()?

From the javadoc of the ReentrantReadWriteLock class :

void processCachedData() { rwl.readLock().lock(); if (!cacheValid) { // Must release read lock before acquiring write lock 5: rwl.readLock().unlock(); 6: 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 14: rwl.readLock().lock(); 15: rwl.writeLock().unlock(); // Unlock write, still hold read } use(data); rwl.readLock().unlock(); } 

Why should we unlock the read lock before getting the write lock, as the comment says? If the current thread holds a read lock, then it should be allowed to set a write lock when other threads are no longer reading, regardless of whether the current thread holds a read lock. This behavior I would expect.

I expect that updating the lock on lines 5 and 6 and lowering the lock on lines 14 and 15 will be done inside the ReentrantReadWriteLock class. Why is this impossible?

In other words, I would expect the code to work like this:

 void processCachedData() { rwl.readLock().lock(); if (!cacheValid) { // The readlock is upgraded to writeLock when other threads // release their readlocks. rwl.writeLock().lock(); // no need to recheck: other threads can't have acquired // the write lock since this thread still holds also the readLock!!! if (!cacheValid) { data = ... cacheValid = true; } // Downgrade by acquiring read lock before releasing write lock rwl.writeLock().unlock(); // Unlock write, still hold read } use(data); rwl.readLock().unlock(); } 

It looks a lot better and safer to block, right?

Can someone explain the reason for this strange implementation? Thank you

+6
source share
3 answers

The problem with updating read locks to write locks is if two threads try to do this at the same time, this can lead to a deadlock. Consider the following sequence:

  • Thread A: Gets a Read Lock
  • Thread B: gets a read lock (note that both threads now share a read lock).
  • Thread A: trying to get a write lock (blocks, since thread B holds a read lock)
  • Thread B: tries to get a write lock (blocks as thread A holds a read lock)

Now there is a dead end. Neither thread A nor B can continue, and none of them will release the read lock.

+14
source

Javadoc explicitly states that updating read lock write lock is not possible. The reason for this is that it can create a dead end.

  • thread 1 get read lock
  • thread 2 get read lock
  • thread 1 ask to update the write lock
  • thread 2 ask to update write lock

Both threads are now waiting for each other ... forever.

+5
source

Reentrancy allows you to abandon a write lock before a read lock, by acquiring a write lock, then reading lock and then unlocking the write lock. However, updating from a read lock to a write lock is not possible (which results in a lock).

Source: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html

+3
source

Source: https://habr.com/ru/post/1484243/


All Articles