Interview essential: Java AQS Condition implementation analysis [boutique chapter]

Let my people encountered, the calendar of things, because even if I have a little bit better, I'll be satisfied.

This paper finishing from "Java concurrent programming art" of Chapter V: Fangteng Fei Wei Peng HLA - A2

AQS:AbstractQueuedSynchronizer

ConditionObject synchronizer is AQS inner classes, because the operation requires a Condition associated with acquiring the lock, so as an internal type synchronizer more reasonable. Each object contains a Condition queue (hereinafter, referred to as the waiting queue), the queue is critical to achieve the object wait Condition / notification function.

The analysis realized Condition below, including: waiting queue, waiting and notification, referred to below Condition if we do not explain all refer to ConditionObject.

1, waiting queue

Waiting queue is a FIFO queue, each node in the queue contains a reference to a thread, the thread is waiting on the object Condition threads, if a thread calls Condition.await () method, then the thread will release the lock, the node is configured to join the waiting queue and enters the wait state. In fact, the definition of the defined nodes multiplexing synchronizer of nodes, i.e., waits for the synchronous queue and queues static inner classes AbstractQueuedSynchronizer.Node node types are synchronizer.

A queue comprising a Condition, Condition has a first node (firstWaiter) and tail nodes (lastWaiter). The current thread calls Condition.await () method, the current thread will be configured node, the node from the tail and added to the waiting queue, waiting queue basic structure shown in Figure 5-9.

As shown in FIG, Condition has reference end to end node and the new node only needs to point to the original tail node nextWaiter it, and updates to the end node. The above referenced node update process does not use the CAS guarantee, because calling await () method thread must be the thread that acquired the lock, that is to say the process is a lock to ensure thread-safe.

Object of the model on a monitor, the object has a synchronous queue and a wait queue, and the contract Lock (more precisely, the synchronizer) has a plurality of synchronous queue and waiting queue , the corresponding relationship shown in Figure 5- 10 FIG.

2. Wait

Condition of calling await () method (or methods to await the beginning), will make the current thread into the wait queue and release the lock, but the thread state to wait state. When returning from await () method, the current thread must acquire the lock associated with Condition.

If viewed from the perspective of the queue (synchronous queue and wait queue) in the await () method is invoked when the await () method is equivalent to the first node synchronization queue (node ​​acquired the lock) to Condition waiting queue.

Condition of the await () method as follows:

public final void await() throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        // 当前线程加入等待队列
        Node node = addConditionWaiter();
        // 释放同步状态,也就是释放锁
        int savedState = fullyRelease(node);
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            LockSupport.park(this);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
    }
复制代码

This method is called a thread successfully acquired a lock thread synchronization queue is the first node, the method sets the current thread is configured node and added to the waiting queue, and then release the synchronized state, awakened synchronization queue successor node, then The current thread into a wait state.

While waiting in the queue nodes wake up, wake up the thread node is started trying to get in sync. If not awakened by another thread calls Condition.signal () method, but to wait for interrupt threads will throw InterruptedException.

From the queue to see if the current thread wait queue Condition added, the process shown in Figure 5-11.

As shown, the first node synchronization queue waiting queue does not directly added, but by addConditionWaiter () method of the current thread is configured as a new node and add it to the wait queue.

3, inform

Condition of call signal () method, will wake the longest waiting time node (the first node) in the waiting queue, before the wake-node, the node will move to the synchronous queue.

Condition of the signal () method, as shown in Listing 5-23.

Listing 5-23 ConditionObject method of signal

 public final void signal() {
        //isHeldExclusively() AQS 子类实现
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        Node first = firstWaiter;
        if (first != null)
            doSignal(first);
    }
复制代码

This method is called pre-condition is the current thread must obtain a lock, you can see the signal () method was isHeldExclusively () check, which is the current thread must obtain a lock thread. Then get the first node of the queue, the queue will move it to synchronize and use LockSupport nodes thread wakes up.

Figure 5-12 shows a node from the waiting queue to queue synchronization process.

By moving enq (Node node) method, the head node thread queue waiting call to the synchronizer safely synchronous queue. When the node moves to the sync queue, then the current thread using the thread wake LockSupport node.

After the thread wakes up, it will await while cycling () method exit (isOnSyncQueue (Node node) method returns true, the node is already in sync queue), which in turn calls synchronizer acquireQueued () method is added to obtain the synchronization status competition.

After successfully acquiring synchronization status (or lock), thread to be awakened from a previous call await () method returns, this time the thread has successfully acquired the lock.

Condition of signalAll () method, each node is equivalent to wait in the queue are the implementation of a signal () method, the effect is to wait for all the nodes in the queue to move all synchronization queue, and wake up the thread of each node pair.

Personal micro-channel public number:

Personal CSDN blog:

blog.csdn.net/jiankunking

Personal github:

github.com/jiankunking

Guess you like

Origin juejin.im/post/5d3848e951882556d1684532