What is the premise of writing this document? Of course, it is not for us to become excellent, but for us to “quarrel” with the interviewer during the interview and talk about your understanding of AQS?

In many cases, a small enterprise not any “pretend bility, single user usage is pathetic when hundreds of people, but there is a bigger and stronger the vision of the situation, will have to ask you some concurrent related problem, this time let we usually CRUD heart under ten thousand points, critical strike damage against ~

First of all, many of you may not know what AQS is, or you may have only heard of the term AQS, but you may not even know how to spell it.

What exactly is AQS? Is it a thought? How do we usually use this AQS in practical projects? It’s a big head

To sum up, AQS is to give a person a kind of scalp numbness, a confused feeling, Baidu search what is AQS, good guy, a large theory of ancient knowledge lost online, see a few after giving up, or see a few after still don’t understand, learn a fart.

Therefore, based on the above pain points, this article will use the most simple plain words with more than N hand-drawn drawings, to tell you clearly what AQS is.

So that you don’t feel overwhelmed when asked this question in an interview, and at least you can fight back and forth with a semi-skilled interviewer. ~

Now, before WE talk about AQS, let’s talk about the connection between ReentrantLock and AQS

You don’t know what a ReentrantLock is.

Q: What if we use Java and ReentrantLock to lock and release the lock? A: That’s not easy. Lock () adds a lock, unlock() releases a lock.

The above code is very simple, is nothing more than a lock object, lock it and release the lock. At this point, you might wonder what this has to do with AQS.

Don’t worry! Don’t worry! Don’t worry! ReentrantLock or ReentrantReadWriteLock source code to look at, because Java and the release of the lock and lock are based on AQS to achieve most of the Whether their Sync inner class are inherited a call AbstractQueuedSynchronizer thing, this thing we call it AQS. To put it bluntly, already contains an internal AQS object, namely AbstractQueuedSynchronizer types of objects. This AQS object is the key core component of ReentrantLock’s ability to lock and release locks.

Q: Can you explain the underlying implementation of ReentrantLock locking and unlocking?Here comes the big one

What happens if, oh, we lock with the lock() method of ReentrantLock? AQS objects have a core variable called state, which is of type int and represents the locked state. In the initial state, the value of this state is 0. In addition, the AQS contains a key variable that records which thread is currently locked. In the initialization state, this variable is null. It is also named ‘exclusiveOwnerThread’.

The thread then calls the lock() method of ReentrantLock to attempt to lock the state. This locking process directly changes the state from 0 to 1 with the CAS operation. If no one has locked before, then the state value must be 0, and thread 1 can successfully lock. Once thread 1 has successfully locked, you can set the current locked thread to itself. So if you look at the picture below, it’s thread 1 running up to lock.

In fact, when you see here, you have no sense of AQS, just like the appearance of love. In fact, it is a core component of the package, which has a core called state and lock thread variables, etc., to maintain some of the lock state.

ReentrantLock ReentrantLock ReentrantLock ReentrantLock ReentrantLock ReentrantLock ReentrantLock ReentrantLock ReentrantLock ReentrantLock ReentrantLock That is, a lock can be added more than once, called reentrant locking. I’m going to show you the code by hand.

In fact, thread 1 can re-enter the lock once, so it can re-enter the lock multiple times. Each time the lock is added, the value of state is incremented by 1, and nothing else changes.

Q: What happens if thread 1 locks and thread 2 runs to lock?

Thread 2 runs up and sees, oops! State is not zero, right? Someone beat you to it? The CAS operation will fail to change state from 0 to 1, because state is currently 1, indicating that someone has locked it!

How did someone beat me to thread 2? And then thread 2 will look and say, did you lock it? It then runs to “lock thread”, which explicitly records that thread 1 is holding the lock, so thread 2 has failed to lock.

Here’s a picture to give you a taste of the process:

Then, thread 2 will put themselves in a waiting queue of AQS, failed because they tried to lock, at this point is to put yourself in the queue waiting, waiting for the thread 1 after releasing the lock, they can try to lock again, this is like like goddess being robbed, only some into the spare tire, such as the goddess with people don’t break up. I could be with my beloved goddess.

So you can see that AQS is so central! AQS also has a wait queue for threads that fail to lock! Commonly known as spare tire!

Again, here’s a picture to give you a taste of it:

Thread 1 then releases the lock after executing its own business logic code! If the state value is 0, then the lock will be released completely, and the “lock thread” variable will also be set to NULL! Without further ado, picture above!!

Next, thread 2 finally has a chance to wake up from the head of the waiting queue to try locking again.

Good! Thread 2 now attempts to lock again, again using the CAS operation to change state from 0 to 1, which will be successful. After success, the lock will be successful, and the state will be set to 1.

In addition, the “lock thread” is set to thread 2 itself, and thread 2 itself disconnects from the wait queue.

And then one last picture, just to show you how it works.

conclusion

OK, so far this article, through the process of ReentrantLock lock and lock release, to give you a preliminary talk about some of its underlying dependence on the core principle of AQS.

Basically, you will understand this article and will never worry about being asked in an interview: talk about your understanding of AQS ⭐️⭐️.

In fact, a word summary: AQS is a basic component and send packets, used to achieve all kinds of locks, all kinds of synchronization components.

It contains the state variable, locking threads, wait queues, and other core components of concurrency.