Abstractqueuedsynchronizer source code analysis (implementation of reentrantlock lock lock)

1. Preface

Abstractqueuedsynchronizer (PS: AQS for short) is used in many places in Java, such as reentrantlock and thread pool. This part is often asked during the interview. Today, take reentrantlock as an example to deepen the understanding of AQS through the source code

2. lock

Generally, our usage is as follows:

We don't know what lock(), unlock(), did. We'll uncover her mystery step by step

2.1. lock

As you can see, reentrantlock defaults to nonfairsync (non fair lock)

2.2. NonfairSync

As you can see, first judge whether the synchronization state is 0. If it is 0, the critical resource is not occupied, and set the state to 1. The current thread obtains this resource and can access it; Otherwise, call the acquire (1) method to try to obtain access control of the resource.

2.3. tryAcquire

Try to get it again

If the current synchronization status is 0, it is the same as before. Set the status to 1, the current thread obtains access, and returns true

If the owner thread of the current resource is the current thread, the status will be incremented by 1, and the current thread will still gain access, and return true

If none of the above is true (PS: resources are occupied by other threads), false is returned

2.4. acquireQueued

If the tryacquire method in the previous step returns false, continue to call the acquirequeueueueueueued method to add the thread to the queue (PS: the end of the linked list)

Before adding to the linked list, it is encapsulated into a node object

Construct the current thread as a node object. The mode of the node is exclusive, then add it to the tail of the linked list (or queue), and finally return the node

There are two special nodes: the head node of the waiting queue and the tail node of the waiting queue

Next, add the node just constructed to the queue

If the predecessor node of the current node is the head node, and the current node tries to obtain resources again (tryacquire method), it happens to succeed, so everyone is happy

If the predecessor node of the current node is not a head, and the current node does not preempt resources, the loop will continue until the state of the predecessor node becomes signal, and the current thread will be suspended

3. unlock

If the owner thread of the resource is not the current thread, an exception is thrown

If the current resource synchronization state minus 1 is exactly 0, it will be released successfully, the synchronization state will be set to 0, the resource owner thread will be set to null, and the successor node of head will be awakened

4. Summary

Lock

1. Default unfair lock (PS: the current thread is not directly added to the waiting queue, but tries to obtain it first. If it fails, it will be added to the queue, and it will try again when adding)

2. The frontage resource has a synchronization status. 0 indicates that there is no thread currently occupied, so the resource can be obtained directly (locking succeeded)

3. If the resource owner thread is the current thread, the state increases by 1 and the lock can still be obtained

3. After locking is successful, set the synchronization status to 1 and the resource owner thread to the current thread

4. If it fails, it will be encapsulated as a node and added to the waiting queue (linked list). At this time, it will try (preempt) again as before

5. Preemption is unsuccessful. It is added to the waiting queue and the thread is suspended

Unlock

1. Throw an exception if the resource owner thread is not the current thread

2. Wake up the next node

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>