"Java Concurrency Programming Combat"-–aqs (iv): CLH synchronization Queue

Source: Internet
Author: User
Tags cas

In "Java Concurrency Programming Combat"-"J.U.C": CLH queue lock mentioned, Aqs inside the CLH queue is a transformation of CLH synchronization lock. It is mainly reformed from two aspects: the structure of node and the mechanism of node waiting. In the structure, the head node and the tail node are introduced, they point to the head and tail of the queue respectively, the attempt to acquire the lock, the queue, the release lock and other implementations are related to the tail-end nodes, and each node introduces the references of the precursor and subsequent nodes, and the wait mechanism is changed from the original spin to the blocking wake. The structure is as follows:

Knowing its structure, let's look at his implementation. The acquire () method of Aqs is called when the thread acquires the lock, and the first attempt to acquire the lock will join the CLH queue if it fails:

Public final void acquire (int arg) {        if (!tryacquire (ARG) &&            acquirequeued (Addwaiter (node.exclusive), ARG))            selfinterrupt ();    }

Addwaiter:

Private node Addwaiter (node mode) {        node node = new Node (Thread.CurrentThread (), mode);        Node pred = tail;        if (pred! = null) {            Node.prev = pred;            if (Compareandsettail (pred, node)) {                pred.next = node;                return node;            }        }        Enq (node);        return node;    }

This is the implementation of Addwaiter (), before we clear this code we have to look at a more important thing, NODE,CLH queue node. The source code is as follows:

Static Final class Node {/** thread has been canceled */static final int CANCELLED = 1;                        /** the subsequent thread of the current thread needs to be Unpark (awakened) */static final int SIGNAL =-1;                        /** thread (in CONDITION sleep state) waits for CONDITION to wake up */static final int CONDITION =-2;            /** shared lock */static final node shared = new node ();            /** Exclusive lock */static final Node EXCLUSIVE = null;            volatile int waitstatus;            /** Front node */volatile node prev;                        /** successor node */volatile node next;            volatile thread thread;            Node Nextwaiter;            Final Boolean isShared () {return nextwaiter = = SHARED;                }/** gets the forward node/final node predecessor () throws nullpointerexception {node p = prev;                if (p = = null) throw new NullPointerException ();          Else          return p;  }/** * Three constructors */node () {} node (thread Thread, node                mode) {This.nextwaiter = mode;            This.thread = thread;                } Node (thread thread, int waitstatus) {this.waitstatus = Waitstatus;            This.thread = thread; }        }

In this source code there are three values (CANCELLED, SIGNAL, CONDITION) to pay particular attention to the node mentioned earlier in the CLH queue has a status bit, which is closely related to the state of the thread:

CANCELLED = 1: The node will be set to cancel if it is timed out or interrupted, the node being canceled will not participate in the competition, he will keep the cancellation state will not change to another State;

SIGNAL =-1: Its successor is blocked, and the wake-up operation is required;

CONDITION =-2: Indicates that the node is in the conditional queue because it waits for a condition to be blocked;

0: The new node is generally 0.

Into row

When a thread attempts to acquire a lock, if it fails to join the CLH queue, the main process in into row is: tail executes the new node, and then points the node's successor to the old tail value. Note that in this process there is a CAS operation that uses spin until it succeeds. The code is as follows:

for (;;) {            Node t = tail;            Node.prev = t;            if (Compareandsettail (t, node)) {                t.next = node;                return t;            }        }

In fact, this code exists in the Enq () method.

Dequeuing

When a thread is locked, a "dequeue" is required, and the main work of the dequeue is to wake up its successor (usually the head node) and let all threads proceed in an orderly manner:

Node h = head;            if (h! = NULL && H.waitstatus! = 0)                unparksuccessor (h);            return true;

Cancel

If a thread is canceled because a timeout or interrupt involves a cancellation, the node will not participate in the lock competition, and it will wait for GC to recycle. The main process of cancellation is to remove the node of the canceled state, and the process of removal is relatively simple. By setting its state to cancelled and then executing its predecessor node's pred, the process will still be a CAS operation:

Node.waitstatus = node.cancelled; Node pred = Node.prev; Node prednext = Pred.next; Node next = Node.next;

Hang Up

We understand that the CLH queue of Aqs is compared to the original CLH queue lock, which uses a deformation operation to change the spin mechanism to a blocking mechanism. The current thread will first detect if it is a head node and attempt to acquire a lock, and if the current node is a head node and the lock is successfully acquired, it is returned directly, the current thread is not blocked, or the current thread is blocked:

for (;;) {    if (Node.prev = = head) if (attempt to acquire Lock succeeded) {         head=node;         Node.next=null;         return;     }   Blocking Threads}


Reference

1. Java concurrency framework--aqs blocking queue Management (ii)

2. Java concurrency framework--aqs blocking Queue Management (iii)

"Java Concurrency Programming Combat"-–aqs (iv): CLH synchronization Queue

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.