Java Multithreading--JUC package source Code Analysis 17--weak consistency and no lock queue __ Non-lock queue

Source: Internet
Author: User
Tags cas int size lock queue

-Weak consistency of Concurrenthashmap
-Weak consistency of Synchronousqueue
-Weak consistency of exchanger
-Weak consistency of the Linux kernel lock-free queues
Summary

Through the previous series of source analysis, we basically covered all the components of the JUC package. In many of these components, we always see a shadow of something: CAS.

Quite a lock, its atomic particle size is smaller, it only acts on a basic variable (such as an integer, Long, or reference), rather than lock-like, global locking, so its concurrency is greater.

But there are always 2 sides to everything, bringing a high degree of concurrency, but also brings another problem: "weak consistency."
Because the existence of "weak consistency" greatly increases our coding difficulty. In the previous Concurrenthashmap,exchanger, in Synchronousqueue's analysis, we all felt, to some extent, the coding complexity of "weak consistency".

This paper tries to make a comprehensive comb of the "weak consistency problem" mentioned above, and analyzes the "authentic" lock-free queue of the Linux kernel and the weak consistency problem that it faces.

Hopefully in the end, there is a deep understanding of "weak consistency," which makes it much easier to understand why "weak consistency" has created a lot of complexity in coding. weak consistency of Concurrenthashmap weak consistency of case1:clear function

Clear execution is complete, and there are still elements in the map.
Reason: Because each segment is locked separately and the next segment is clear, the last segment lock is released, at which point the other threads can put elements inside. case2:put into the element, get out of NULL

Reason: because tab[index] = new Hashentry case 3:put into the element, get out is empty

Reason: Because get does not lock, before putting executes count = C that line of code, although the element is put in, but because there is no happen before constraints, it may not be. (The specific code is not listed here again, see the previous Concurrenthashmap source code analysis) Synchronousqueue weak consistency

As we know before, Transferqueue/transferstak are all based on a one-way list. Multi-threaded access to this list, and did not lock, just to Head/tail for CAS access. As a result, the following issues of "weak consistency" are created:

Transferqueue.transfer
        Object Transfer (Object E, Boolean timed, long Nanos) {
            Qnode s = null;//Constructed/reu Sed as needed
            boolean isdata = (e!= null);

            for (;;) {
                Qnode t = tail;
                Qnode h = head;
                if (t = = NULL | | h = NULL)        
                    continue;                    

                if (h = = T | | t.isdata = = isdata) { 
                    Qnode tn = t.next;
                    if (t!= tail)            //t = tail, there is a T!= tail here. This is because there are other threads doing CAS operations on tail. Thus causing inconsist read
                        continue ...
          .
}

weak consistency of exchanger
 Private object Doexchange (object item, Boolean timed, long Nanos) {node me = new Node (i                 
        TEM);   
        int index = Hashindex ();                            

        int fails = 0; for (;;)                             
            {Object y;
            Slot Slot = Arena[index];     
            if (slot = = null) createslot (index); else if ((y = Slot.get ())!= null && slot.compareandset (y, null)) {//slot There's someone waiting to swap, empty the slot , node takes out, and two people interact in node.               
                Give the slot to the people behind, do the interactive location node you = (node) y; if (You.compareandset (null, item)) {//slot emptied, was about to be ready to swap in node, but was robbed by another thread, causing you.compareandset failure. 
                    Mantis flutter Cicada, Siskin Locksupport.unpark (You.waiter); 
                return you.item;
 } } 。。。 }

These problems occur because Slot.comareandset and you.compareandset, respectively, are atoms, but together, they are not atomic. weak consistency of the Linux kernel lock-free queues

In the Linux kernel, there is a completely unlocked queue kfifo based on Ringbuffer, not even CAs. Of course, it has a prerequisite: only 1 read 1 write.
Source links are as follows:
Https://github.com/opennetworklinux/linux-3.8.13/blob/master/kernel/kfifo.c

struct Kfifo {   
    unsigned char *buffer;    /* The buffer holding the data *   
    /unsigned int size;    /* The size of the allocated buffer *   
    /unsigned int in;    /* The data is added at offset (in% size) */   
    unsigned int out;    /* The data is extracted from off. (out% size) */   
    spinlock_t *lock;    /* Protects concurrent modifications * *   
;

When the team, the operation variable in;

unsigned int __kfifo_in (struct __kfifo *fifo, const void *buf, unsigned int len) {UN

    signed int l;
    L = kfifo_unused (FIFO);

    if (Len > L) len = l;
    Kfifo_copy_in (FIFO, buf, Len, fifo->in);   Fifo->in = Len;
The team, in the pointer to move forward return Len; } unsigned int __kfifo_out (struct __kfifo *fifo, void *buf, unsigned int len) {len = __kfifo_out_peek (FIFO,
    BUF, Len);  Fifo->out = Len;
Out pair, out pointer move forward return Len; static inline unsigned int kfifo_unused (struct __kfifo *fifo) {return (Fifo->mask + 1)-(FIFO->IN-FIFO-&G  T;out); Determine unused space} unsigned int __kfifo_out_peek (struct __kfifo *fifo, void *buf, unsigned int len) {unsigned int l

    ;
    L = fifo->in-fifo->out;

    if (Len > L) len = l;
    Kfifo_copy_out (FIFO, buf, Len, fifo->out);
return Len; }

It can be seen from the above, whether it is int, out, or to determine whether the queue is empty/full, there is no lock, there is no CAs, so can do this because of 2 prerequisites:
(1) Only 1 read 1 write, one operation in, one operation out
(2) Weak consistency: When placed, the queue is not full, may be judged to be full, when taken, the queue is not empty, but judged to be empty. But there is no relationship, the producer/consumer is a circular call, this time can not be taken, the cycle back to try again, may be taken.

Of course, about KFIFO, there are some other tips in the inside, this time no longer detailed. You can join the following article
http://blog.csdn.net/linyt/article/details/5764312 Summary

In the above, we have enumerated many examples of "weak consistency" to sum up:
(1) So there will be this problem, because the lock is not added, or the size of the lock is too small (CAS). No way like lock, you can have a critical section, "Large area" of the lock, to achieve the operation of a combination of atomic operations.
(2) The solution to this problem is usually "cyclic retry". Since inconsistent read, read it again.

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.