preface
To recap:
- Multiple threads can get through a door in three minutes!
- Thread source code analysis
- Multithreading foundation essential knowledge points! Read the learning multithreading twice the result with half the effort
- Learn about the Java locking mechanism
Only skinheads can be strong!
I originally intended to subclass Lock in this section, but seeing the concept of AQS, I can say that all subclass Lock implementations are based on AQS.
I’ve seen him in interview questions, but I never knew what he was. So I will talk about AQS, at least know what its concept is, right
So let’s get started
What is AQS?
First, let’s generalize what JUc is: juc stands for package (java.util.concurrnt).
- Don’t let anyone fool you into thinking the JUc is something awesome. It actually refers to the bag
We can see that the Lock package has three abstract classes:
- AbstractOwnableSynchronizer
- AbstractQueuedLongSynchronizer
- AbstractQueuedSynchronizer
Generally: AbstractQueuedSynchronizer AQS for short
Our two common locks like Lock are based on it:
So let’s see what AbstractQueuedSynchronizer, see what a class is the fastest way is to see it at the top of the comments
After a thorough reading, the following key information can be summarized:
- AQS is basically a framework that allows us to implement locks
- The key of internal implementation is: fifO queue, state state
- ConditionObject is an internal class defined
- There are two threading modes
- Exclusive mode
- Sharing model
- Locks in the LOCK package (commonly used ReentrantLock, ReadWriteLock) are built based on AQS
- We usually call AQS synchronizers
Second, a brief look at AQS
As mentioned above, the most important part of AQS is the status and queue. Let’s take a look at the source code of AQS.
2.1 Synchronization Status
Use the volatile modifier for thread visibility:
CAS algorithm is used to modify the state value:
2.2 FifO queue
This queue is called the CLH queue (three names) and is a bidirectional queue
Look at the composition of the queue source code:
static final class Node {
/ / Shared
static final Node SHARED = new Node();
/ / exclusive
static final Node EXCLUSIVE = null;
// The thread was cancelled
static final int CANCELLED = 1;
// Subsequent threads need to wake up
static final int SIGNAL = -1;
// Wait for the condition to wake up
static final int CONDITION = -2;
// Shared synchronous state acquisition will propagate unconditionally
static final int PROPAGATE = -3;
// The initial state is 0
volatile int waitStatus;
// The front node
volatile Node prev;
// Subsequent nodes
volatile Node next;
volatile Thread thread;
Node nextWaiter;
final boolean isShared(a) {
return nextWaiter == SHARED;
}
final Node predecessor(a) throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() { // Used to establish initial head or SHARED marker
}
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread; }}Copy the code
2.3 acquire method
The process of acquiring an exclusive lock is defined in acquire, which uses the template design pattern, implemented by subclasses
Procedure: Acquire (int) attempts to acquire a resource, and if it fails, the thread is inserted into the wait queue. After the wait queue is inserted, acquire(INT) does not give up acquiring resources, but determines whether to continue acquiring resources according to the status of the front node. If the front node is the head node, continue trying to acquire resources; if the front node is in SIGNAL state, interrupt the current thread; otherwise, continue trying to acquire resources. Until the current thread is park() or acquires a resource, acquire(int).
Source:
- Blog.csdn.net/panweiwei19…
2.4 release method
The process of releasing an exclusive lock is defined in acquire, which also uses the template design pattern, implemented by subclasses ~
Procedure: first call the subclass’s tryRelease() method to release the lock, then wake up the successor node, during the wake up process, need to determine whether the successor node meets the condition, if the successor node is not and is not invalidated, wake up the successor node, otherwise from the tail node forward to find the appropriate node, if found, wake up.
Source:
- zhuanlan.zhihu.com/p/27134110
Three, the last
To summarize what AQS really are:
- Many of the blocking classes in the JUC package are built on AQS
- AQS can be said to be a framework for implementing synchronization locks and synchronizers, and many implementation classes are built on the basis of it
- The default implementation of waiting queues in AQS, subclasses can just rewrite part of the code to implement (a lot of template code)
Interested students can go to see the source code and the following links to continue learning, I will not tell here. Simply go over the AQS again
Lock explicit Lock implementation tomorrow
References:
- Blog.csdn.net/panweiwei19…
- zhuanlan.zhihu.com/p/27134110
- Cmsblogs.com/?page_id=11…
Open source project (6 K STAR) :Github.com/ZhongFuChen…
If you want to follow my updated articles and shared dry goods in real time, you can search Java3y on wechat.
The content of the PDF document is typed by hand. If you don’t understand anything, you can ask me directly (the official account has my contact information).