The problem

(1) Positioning of AQS?

(2) An important part of AQS?

(3) The design mode used by AQS?

(4) The overall process of AQS?

Introduction to the

Is the full name of AQS AbstractQueuedSynchronizer, its location is for almost all the locks in Java and synchronizer provides a basic framework.

In the previous chapter, we learned the source code of ReentrantLock, ReentrantReadWriteLock, Semaphore, CountDownLatch. Today, we come to a summary of AQS.

State variable

AQS defines a state variable state, which can be used in the following two ways:

(1) Mutex

When AQS is only implemented as a mutex, the lock is acquired every time the atomic update state value is successfully changed from 0 to 1. Reentrant is achieved by continuously increments of the atomic update state by 1.

(2) Mutex + shared lock

When AQS needs to be both mutually exclusive and shared, the low 16 bits store the mutual-exclusive status and the high 16 bits store the shared status, which are mainly used to implement read/write locks.

A mutex is an exclusive lock. Only one thread is allowed to own it at a time. When a thread is exclusive, other threads cannot obtain the mutex or the shared lock, but it can obtain the shared lock itself.

A shared lock allows multiple threads to own the lock. Once one thread owns the shared lock, all threads (including themselves) can no longer acquire the mutex, but can acquire the shared lock.

AQS queue

AQS maintains a queue in which any thread that fails to acquire a lock (other than tryLock()) will queue, waiting for the lock to be released and waking up the next queued thread (in mutex mode).

Condition queue

ConditionObject is another very important internal class in AQS, which implements the Condition interface and is primarily used for conditional locking.

ConditionObject also maintains a queue that is used to wait for the condition to be set up. When the condition is set up, other threads move the element to the AQS queue and wait for the thread holding the lock to be awakened.

Condition is typically implemented in BlockingQueue. When the queue is empty, the thread fetching the element blocks on the notEmpty Condition. Once an element is added to the queue, the notEmpty Condition is notified to move the element in its queue to the AQS queue to be awakened.

Template method

The AQS abstract class is the master of the template method design pattern. It defines a series of template methods, such as the following:

// Get the mutex
public final void acquire(int arg) {
    // tryAcquire(ARg) requires subclass implementation
    if(! tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }// Obtaining the mutex can be broken
public final void acquireInterruptibly(int arg)
        throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    // tryAcquire(ARg) requires subclass implementation
    if(! tryAcquire(arg)) doAcquireInterruptibly(arg); }// Get the shared lock
public final void acquireShared(int arg) {
    // tryAcquireShared(arg) requires subclass implementation
    if (tryAcquireShared(arg) < 0)
     doAcquireShared(arg);
}
// Obtaining the shared lock can be interrupted
public final void acquireSharedInterruptibly(int arg)
        throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    // tryAcquireShared(arg) requires subclass implementation
    if (tryAcquireShared(arg) < 0)
        doAcquireSharedInterruptibly(arg);
}
// Release the mutex
public final boolean release(int arg) {
    // tryRelease(arg) requires subclass implementation
    if (tryRelease(arg)) {
        Node h = head;
        if(h ! =null&& h.waitStatus ! =0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}
// Release the shared lock
public final boolean releaseShared(int arg) {
    // tryReleaseShared(arG) requires subclass implementation
    if (tryReleaseShared(arg)) {
        doReleaseShared();
        return true;
    }
    return false;
}
Copy the code

Obtain lock, lock release these methods are basically interlaced in ReentrantLock, ReentrantReadWriteLock, Semaphore, CountDownLatch source code parsing, now look at them are not more comfortable, if the beginning to see these source code, will inevitably be very halo.

Methods that require subclass implementation

Here are some of the most important template methods in AQS:

// Used in mutually exclusive mode: try to obtain the lock
protected boolean tryAcquire(int arg) {
    throw new UnsupportedOperationException();
}
// Used in exclusive mode: attempt to release the lock
protected boolean tryRelease(int arg) {
    throw new UnsupportedOperationException();
}
// In shared mode: try to obtain the lock
protected int tryAcquireShared(int arg) {
    throw new UnsupportedOperationException();
}
// In shared mode: try to release the lock
protected boolean tryReleaseShared(int arg) {
    throw new UnsupportedOperationException();
}
// Returns true if the current thread owns the lock
protected boolean isHeldExclusively(a) {
    throw new UnsupportedOperationException();
}
Copy the code

Why not define these methods as abstract methods?

Because subclasses only need to implement some of these methods to implement a synchronizer, there is no need to define an abstract method.

conclusion

Today we talked about several important components of AQS, understand these several structures, AQS to you will have no secret at all, of course, when the interview can answer these points clearly, the interviewer will be immediately bright.

(1) State variable state;

(2) AQS queue;

(3) Condition queue;

(4) Template method;

(5) methods that need to be implemented by subclasses;

eggs

After the previous learning, can you briefly describe the general process of AQS obtaining mutex?

Here tong elder brother will not answer, I believe that after learning the previous content, answer this question is not a problem, can not answer the following recommended reading to read several times ^^

Recommended reading

The beginning of the Java Synchronization series

2, Unbroadening Java magic class parsing

JMM (Java Memory Model)

Volatile parsing of the Java Synchronization series

Synchronized parsing of Java series

6, Deadknock Java synchronization series write a Lock Lock yourself

7. AQS of The Java Synchronization series

ReentrantLock (a) — fair lock, unfair lock

ReentrantLock – Conditional lock

ReentrantLock VS Synchronized Java series

ReentrantReadWriteLock source code parsing

Semaphore source code analysis of Semaphore Java synchronization series

CountDownLatch source code parsing

Welcome to pay attention to my public number “Tong Elder brother read source code”, view more source code series articles, with Tong elder brother tour the ocean of source code.