AQS a little learning

 

private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // Must initialize
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

 

 

This is a small part of AQS. The function is to insert a node in the queue. In order to save overhead, the AQS queue is in the lazy initialization mode. When inserting into the queue, the head node and tail are initialized. node. Original Notes

 

CLH queues need a dummy header node to get started. But we don't create them on construction, because it would be wasted effort if there is never contention. Instead, the node is constructed and head and tail pointers are set upon first contention. 

 

First assume that there is only one thread. When entering this code for the first time, enter the fourth line, and then set the head node correctly, which is equivalent to the head and tail pointing to a new node node. Because it is an infinite loop, The program will run to line 7. After running compareAndSetTail(t, node), tail points to the new tail node, which is the input parameter node passed in by the function, the prev pointer of node points to the original tail, and the next pointer of the original tail points to node

 

private final boolean compareAndSetHead(Node update) {
        return unsafe.compareAndSwapObject(this, headOffset, null, update);
    }

 The above code atomically sets the head field of the current object. In thought, it is similar to the optimistic lock of the database, set head = update where head=null. In multi-threaded mode, only one thread can set successfully. Similarly, add a node to the queue tail. , and only one thread can succeed. If it does not succeed, because the calling program writes an infinite loop, it will add nodes to the new tail until it succeeds.

private final boolean compareAndSetTail(Node expect, Node update) {
        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
    }

 

 To sum up, this code cleverly avoids the multi-threading problem, adds a node to the queue, and uses lazy initialization, head node and tail node

 

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326578840&siteId=291194637
AQS
AQS