The principle of read-write lock ReentrantReadWriteLock

Foreword

Introduced in front of java in exclusive locks, shared locks underlying implementation mechanism herein, this further, very useful learning to read and write locks. In view of the read-write lock to be more complex than other locks, did not want to heap a big wave of text herein, this will attempt to graphically illustrate, the read-write lock mechanism described in another way, given my limited level, where if there is an error, please let me know.


Fair Read-Write Lock

ReentrantReadWriteLock locking strategy, there are two strategies into equity and non-equity strategies, some small difference between the two, for ease of understanding, this section will form an example to illustrate the multi-threaded, use read-write lock fairness policy is how to deal with of.

First look at the upcoming appearances of partners, we will be playing a total of several threads, as well as read and write mechanism for implementing the AQS synchronization queue. Each thread R (0) W (0) indicates that the current thread holds the read-write lock number.

Write pictures described here

Next, we look at a step by step fairness policy multithreaded concurrent read and write mechanism is like.

1. A thread requests a read lock, then no lock contention, A 1 acquires a read lock, i.e. the number of thread A reentry 1, as follows:

Write pictures described here

2. Thread B requests a read lock, since there is no waiting AQS node currently occupied in the read lock state (thread A occupies a read lock), the read lock is acquired successfully B, as follows:

Write pictures described here

3. At this time, the thread C requests a write lock, the other two because of the current thread has a read lock, write lock acquisition has failed, C thread queues, as follows:

Write pictures described here

AQS initialization creates an empty head node, C into the queue, then sleeps, waiting for the other thread releases the lock wake.

4. Thread D has come, the thread D want to get a read lock, although when in possession of the stage in a read lock, but does not currently possess any number of D read lock, and synchronization has been waiting in queue node, this time, due to the fairness policy, D forced, a word, etc., as shown below:

Write pictures described here

5. At this time, the thread A executes finished, release the read lock, because the B still holds a read lock, so after the release read lock is still not fully released, write lock is still no opportunity to perform, as shown below:

Write pictures described here

6. This time, B also performs over, after the implementation, read locks have been released, this time will wake ranked team head node synchronizer C, C successfully acquired a write lock, as shown below:

Write pictures described here

7.一旦任何一个线程获取了写锁,除了该线程自己,其它线程都将无法获取读锁和写锁,这时候,线程C再次请求一个读锁,这是允许的,但反过来如果一个线程先获取了读锁,再获取写法则是不行的。这时候的状态如下图所示:

Write pictures described here

8.这时候假设线程E也来了,E想获取读锁,由于当前处于写锁状态,直接入队,如下所示:

Write pictures described here

9.这会C终于把活干完了,把读锁和写锁都给释放了,然后线程D被唤醒,获取了读锁,如下图所示:

Write pictures described here

10.这时候,如果再来一个线程,比如A,也想获取读锁,由于节点中还有线程E在等待,而且当前线程A没有获取任何读锁,不是重入状态,所以只能置入队尾,如下图所示:

Write pictures described here

11.这时候,如果D再次调用了一次获取读锁,由于D属于可重入状态,所以直接把读锁+1即可,如下图所示:

Write pictures described here

12.由于D获取的是读锁,同步队列中的E等待的也是读锁,所以E会被唤醒,获取读锁继续执行,如下图所示:

Write pictures described here

13.同样的,由于线程A获取的是读锁,在E执行后,会唤醒线程A,A也可以获得读锁,并继续执行,如下图所示:

Write pictures described here

14.最后大家各自执行,悄然退场。


非公平读写锁

接下来我们再来看一下非公平策略读写锁机制又是如何的,为了更好的对比,我们沿用公平锁的流程。

由于获取读锁的逻辑比较复杂,我们在这里先简单进行归纳:

a. 如果当前全局处于无锁状态,则当前线程获取读锁

b. 如果当前全局处于读锁状态,且队列中没有等待线程,则当前线程获取读锁

c. 如果当前全局处于写锁占用状态(并且不是当前线程占有),则当前线程入队尾

d. 如果当前全局处于读锁状态,且等待队列中第一个等待线程想获取写锁,那么当前线程能够获取到读锁的条件为:当前线程获取了写锁,还未释放;当前线程获取了读锁,这一次只是重入读锁而已;其它情况当前线程入队尾。之所以这样处理一方面是为了效率,一方面是为了避免想获取写锁的线程饥饿,老是得不到执行的机会

e. 如果当前全局处于读锁状态,且等待队列中第一个等待线程不是写锁,则当前线程可以抢占读锁

获取写锁相对就比较简单了,规则如下:

h. 如果当前处于无锁状态,则当前线程获取写锁

i. 如果当前全局处于读锁状态,当前线程入队尾

j. 如果当前全局处于写锁状态,除非是重入获取写锁,否则入队尾

接下来我们看一遍流程:

1.线程A请求一个读锁,全局处于无锁状态,根据规则a,线程A获取了锁,如下图所示:

Write pictures described here

2.线程B请求一个读锁,根据规则b,线程B可以获取到读锁

Write pictures described here

3.这时候,线程C请求一个写锁,由于当前其他两个线程拥有读锁,写锁获取失败,线程C入队列(根据规则i),如下所示:

Write pictures described here

AQS初始化会创建一个空的头节点,C入队列,然后会休眠,等待其他线程释放锁唤醒。

4.线程D也来了,线程D想获取一个读锁,根据读锁规则d,队列中第一个等待线程C请求的是写锁,为避免写锁迟迟获取不到,并且线程D不是重入获取读锁,所以线程D也入队,如下图所示:

Write pictures described here

5.这时候,线程A执行完了,释放了读锁,由于B仍然占有读锁,所以释放后读锁仍然没有完全释放,写锁仍然没有机会执行,如下图所示:

Write pictures described here

6.这次,B也执行完了,执行完后,读锁全部释放,这时候会唤醒排在同步器队头的节点C,C成功获取一个写锁,如下图所示:

Write pictures described here

7.一旦任何一个线程获取了写锁,除了该线程自己,其它线程都将无法获取读锁和写锁,这时候,线程C再次请求一个读锁,这是允许的,但反过来如果一个线程先获取了读锁,再获取写锁则是不行的。这时候的状态如下图所示:

Write pictures described here

8.这时候假设线程E也来了,E想获取读锁,由于当前处于写锁状态,直接入队,如下所示:

Write pictures described here

9.这会C终于把活干完了,把读锁和写锁都给释放了,然后线程D被唤醒,获取了读锁,如下图所示:

Write pictures described here

10.这时候,如果再来一个线程,比如A,也想获取读锁,虽然等待队列中,E线程刚好还没被唤醒,但A线程是可以抢占读锁的(这里假设抢占到了),这个跟公平锁有明显的区别,如下图所示:

Write pictures described here

11.这时候,如果D再次调用了一次获取读锁,由于D属于可重入状态,所以直接把读锁+1即可,如下图所示:

Write pictures described here

12.由于当前状态下处于读锁状态,前面的线程D其实醒来后,是会同时唤醒线程E的,所以线程E也醒过来继续干活了,如下图所示:

Write pictures described here

13. The synchronous queue without waiting thread, and each thread after the implementation of all peace prevail.

to sum up

Considering the diversity of business and contracting of the tools provided in most of java5 while providing a fair and non-equity strategies, both strategies, in general, non-fair throughput lock will be relatively large, so by default under the non-equity strategies are used.

Benpian tried to keep it simple way to articulate the read-write lock mechanism, in order to intuitive, we consider only simple abstract way, at the time of actual implementation, will use the CAS to compete lock. Especially in non-equity strategies 10th step, it is possible in this case to obtain a read lock E. In many cases, we have a general understanding of the implementation steps, after the process, go to the taste of the source, will be more relaxed.

Finally, it is recommended that everyone in the understanding of the idea, to see how much your source code, to think, learn is their own thing.

Original: https: //blog.csdn.net/yanyan19880509/article/details/52435135

Published 740 original articles · won praise 65 · Views 100,000 +

Guess you like

Origin blog.csdn.net/qq_41723615/article/details/104348300