Java concurrent programming summary 8: ReentrantReadWriteLock

General see: Detailed interpretation of write lock ReentrantReadWriteLock

Reading and writing are allowed to be accessed by multiple reader threads at the same time, but when the writer thread accesses, all reader threads and other writer threads will be blocked .

In conclusion:

  1. Fairness selection : Supports unfairness (default) and fair lock acquisition methods, and throughput is still unfair better than fairness;
  2. Reentrancy : Supports reentrancy, the same thread can acquire the read lock again after it is acquired, and the same thread can acquire the write lock again after acquiring the write lock, as well as the read lock
  3. Lock downgrade : Follow the order of acquiring the write lock first, then acquiring the read lock and then releasing the write lock, the write lock can be downgraded to a read lock

To be able to thoroughly understand read-write locks, you must be able to understand several issues:

  1. How does the read-write lock record the read-write status separately?
  2. How is the write lock acquired and released?
  3. How are read locks acquired and released?

 

1. Write lock: is an exclusive lock

1. Write lock acquisition tryAcquire : Write locks cannot be acquired by multiple threads at the same time. Obviously, write locks are exclusive locks, and the synchronization semantics of write locks is achieved by rewriting the tryAcquire method in AQS .

In tryAcquire , there is an exclusiveCount (c) method, in which there is an int value EXCLUSIVE_MASK : the high 16 bits of the synchronization state are used to indicate the number of times the read lock is acquired, and the low 16 bits of the synchronization state are used to indicate the number of write lock acquisitions ;

The main logic of tryAcquire is: when the read lock has been acquired by the reader thread or the write lock has been acquired by other write threads, the write lock acquisition fails; otherwise, the acquisition succeeds and supports reentry, increasing the write status.

2. Write lock release tryRelease : Write lock release by overriding the tryRelease method of AQS

The implementation logic of the source code is basically the same as that of ReentrantLock. It should be noted here that to reduce the write state, int nextc = getState() - releases;only the current synchronization state needs to be directly subtracted from the write state . The reason is that the write state we just said is represented by the low 16 bits of the synchronization state. .

2. Read lock: not exclusive lock: shared lock

The read lock is not an exclusive lock, that is, the lock can be acquired by multiple reader threads at the same time, which is a shared lock .

Realizing the synchronization semantics of shared synchronization components requires rewriting the tryAcquireShared method and tryReleaseShared method of AQS.

1. The acquisition of the read lock implements tryAcquireShared:

When the write lock is acquired by other threads, the read lock acquisition fails , otherwise the acquisition succeeds and uses CAS to update the synchronization status.

2. The implementation of read lock release tryReleaseShared:

The read lock release will subtract the read state from the synchronization state ;

3. Lock downgrade:

Read-write locks support lock downgrading: follow the sequence of acquiring write locks first, then acquiring read locks and then releasing write locks. Write locks can be downgraded to read locks , but lock upgrades are not supported (read locks cannot be upgraded to write locks);

 

Four, summary:

The biggest difference between unfairness and fairness lies in the acquisition of write locks :

  • In the unfair strategy, the acquisition of write locks never needs to be queued . This is a consideration of real-time performance optimization, because in most cases the operation time involved in write locks is much longer than read locks, and the frequency is much lower than read locks. Prevent the writer thread from being hungry all the time.
  • The special feature of ReentrantReadWriteLock is that an int value is used to represent two different states (the low 16 bits represent the number of reentrants of the write lock, and the high 16 bits represent the number of uses of the read lock), and the AQS is implemented at the same time through two internal classes. There is no difference between the core part of the two APIs and shared/exclusive locks.

 

Guess you like

Origin blog.csdn.net/ScorpC/article/details/113859093