"Java.util.concurrent package source reading" 161 Kinds of special Blockingqueue:synchronousqueue

Source: Internet
Author: User

Synchronousqueue is a very special kind of blockingqueue, and any action that adds an element must wait for another thread to take away the element before it ends. That is, synchronousqueue itself does not store any elements, which is equivalent to the direct trade of the producer and the consumer hand.

Synchronousqueue has a fair option, if Fair is true, called fair mode, otherwise it is unfair mode.

In fair mode, all waiting producer threads or consumer threads are queued according to the start Wait time, followed by a matching transaction in the order of waiting. This situation is implemented in a queue.

In unfair mode, the exact opposite is followed by the first match, which is implemented with the stack.

     *     /Public Synchronousqueue (boolean  Fair)        {newnew  Transferstack ();    }

Because adding elements and taking away elements is similar to hand-handed trading, for taking elements and adding elements to the operation, Synchronousqueue calls Transferer the same method transfer.

When object is null, it is taken away from the element, used for the consumer thread, otherwise the element is added for the producer thread. So the transfer method is the focus of the analysis.

Abstract Boolean long Nanos);

First look at the transfer method for Transferqueue for fair mode:

Before looking at the code, take a look at the logic:

1. The start queue must be empty.

2. Thread enters the queue, if the queue is empty, add the thread to the queue, and then wait (either a matching thread appears or the request times out to cancel)

3. The second thread enters, and if the previous thread is of a different type, that is, the two can match, then the first thread is removed from the queue.

If it is the same thread, then the procedure is referred to 2.

The basic logic is clear, that is, there are two situations:

1. The queue is empty or the waiting thread in the queue is the same type

2. The waiting thread in the queue is a matching type

Object Transfer (Object E,BooleanTimedLongNanos) {Qnode s=NULL; //e is not a null representation is the generator thread, E is the product, and vice versa is the consumer thread            BooleanIsdata = (E! =NULL);  for (;;) {Qnode T=tail; Qnode h=Head; //tail and head are initialized to a virtual node when the queue is created//so the discovery is not initialized, and the cycle waits until initialization is complete                if(T = =NULL|| H = =NULL)                    Continue; //queue is empty or waits for the same thread type (different types to match)//in both cases, the current thread is added to the wait queue                if(h = = T | | t.isdata = =isdata) {Qnode tn=T.next; //Tail object has been updated, inconsistent read phenomenon, re-cycle                    if(t! =tail)Continue; //adding a thread to the wait queue will update the current tail's next and then//The update tail itself, so that only the next updated condition appears, should//update tail, and then cycle again                    if(TN! =NULL) {Advancetail (T, TN); Continue; }                    //Timeout is set and the remaining wait time is exhausted, no more waiting                    if(timed && nanos <= 0)                        return NULL; //when using S for the first time, create a new node to save the current thread and datato initialize S                    if(s = =NULL) s=NewQnode (E, isdata); //try to update tail Next, add the new node to the back of tail,if it fails, re-cycle it.                    if(!t.casnext (NULL, s)) Continue; //set the newly created node to tailAdvancetail (t, s); //The matching value is returned if the matching thread is waiting for a successful match//Otherwise, the current node is returned, so s and X are the same to indicate that the request was canceledObject x =Awaitfulfill (S, e, timed, Nanos); if(x = =s) {clean (t, s); return NULL; }                    //this time has been matched successfully, s should be ranked in the first waiting thread//if S is still in the queue, you need to update the head. //the way to update head is to take the first node of S as the new head//so you need to reset some properties to make it into a virtual node                    if(!s.isofflist ())                        {Advancehead (t, s); if(X! =NULL) S.item=s; S.waiter=NULL; }                    //x is not NULL to get the data of the matching thread (the consumer gets the producer's data),//so return the data, otherwise return the data itself (the generator returns its own data)                    return(X! =NULL) ?x:e; } Else{//Threads can match//because it is a queue, it matches the first nodeQnode m =H.next; //also need to check for inconsistent reads                    if(t! = Tail | | m = =NULL|| H! =head)Continue; Object x=M.item; //when the match fails, the M is removed from the queue and re-cycled                    if(Isdata = = (x! =NULL) ||//m has been matched.x = = m | |//m has been canceled.!m.casitem (x, E)) {//set M's data with CAs to nulladvancehead (H, M); Continue; }                    //match succeeded, update headadvancehead (H, M); //dismiss the thread wait state of MLocksupport.unpark (M.waiter); //returns the matching data                    return(X! =NULL) ?x:e; }            }        }

Followed by the transfer method for the transferstack of the unfair pattern

The general logic should be the same, the difference is that the queue and outbound operations corresponding to the stack is into the stack and the operation of the stack.

Object Transfer (Object E,BooleanTimedLongNanos) {SNode s=NULL; intmode = (E = =NULL) ?Request:data;  for (;;) {SNode h=Head; //case where the stack is empty or the node type is the same                if(H = =NULL|| H.mode = =mode) {                    if(timed && nanos <= 0) {                        //Check if the top node of the stack has been canceled and if it has been canceled, the popup node//re-loop, then check the new stack top node                        if(H! =NULL&&h.iscancelled ()) Cashead (h, H.next); Else                            return NULL; //Create a new node, and try to put it into the stack}Else if(Cashead (h, s =Snode (S, E, H, mode))) {                        //waits for a match, releases the node if found to be canceled, returns nullSNode m =Awaitfulfill (S, timed, Nanos); if(M = =s) {clean (s); return NULL; }                        //If the match succeeds two nodes are two nodes at the top of the stack//Pop These two nodes out of the window.                        if((h = head)! =NULL&& H.next = =s) cashead (h, S.next); //Help s ' s Fulfiller                        return(mode = = REQUEST)?M.item:s.item; }                } Else if(!isfulfilling (H.mode)) {//The top node of the stack does not match the other threads and can match                    if(H.iscancelled ())//the request for the top node of the stack has been canceledCashead (H, H.next);//Remove stack top element re-cycle//try to put the node into the stack, which is set to the state being matched//That is, isfulfilling returns True .                    Else if(Cashead (H, S=snode (S, E, H, fulfilling|mode))) {                         for (;;) {                            //The top node of the stack (the node of the current thread) matches its next node, and m null means//There is no other node in the stack, because the node in front of the stack, need to pop this node re-cycleSNode m =S.next; if(M = =NULL) {Cashead (s),NULL); S=NULL;  Break; }                            //this time there are nodes to match, try to match these two nodesSNode MN =M.next; //m and S match successfully, eject these two nodes, return data, match failed, remove M                            if(M.trymatch (s)) {Cashead (S, MN); return(mode = = REQUEST)?M.item:s.item; } ElseS.casnext (M, MN); }                    }                //the top of the stack is being matched, see Code://Else if (Cashead (H, S=snode (S, E, H, Fulfilling|mode))) {//The approach is basically similar, just here to help other threads match, whether successful or not//we have to recycle .}Else{SNode m=H.next; if(M = =NULL) Cashead (H,NULL); Else{SNode mn=M.next; if(M.trymatch (h)) Cashead (H, MN); ElseH.casnext (M, MN); }                }            }        }

Transferqueue and Transferstack's algorithm implementation can refer to here

Java.util.concurrent package source reading 161 kinds of special blockingqueue:synchronousqueue

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.