Longadder of Java concurrent programming and Longaccumulator source code exploration

Source: Internet
Author: User
Tags array length cas volatile

I. Longadder principle

The Longadder class is a new atomic operation class for JDK1.8. Atomiclong provides non-blocking atomic operations through the CAS algorithm, and performance is good compared to a Synchronizer with a blocking algorithm, but the JDK Development Group is not satisfied because the performance of Atomiclong is unacceptable under concurrent requests.

The following Atomiclong incrementandget code, although Atomiclong uses the CAS algorithm, but after the CAS failed or through an infinite loop of spin-lock not many attempts, which is high concurrency under the low CAS performance reasons. The source code is as follows:

 Public Long Incrementandget () {        for  (;;) {            longget();             Long 1 ;             if (Compareandset (current, next))                 return next;        }    }

Simultaneous operation of a variable at high concurrency n multithreading causes a large number of thread CAs to fail and then spin, resulting in a significant waste of CPU resources and reduced concurrency.

Since the Atomiclong performance problem is due to the fact that too many threads are competing for the same variable at the same time, then if a variable is decomposed into multiple variables, so that the same number of threads compete for multiple resources, will the performance problem soon be solved?

Yes, so the longadder provided by JDK8 is the idea. The following graphs indicate the differences between the two, such as:

such as Atomiclong are multiple threads competing for the same variable scenario at the same time.

As shown, Longadder is internally maintaining multiple cell variables, each with a long variable with an initial value of 0, and in the case of equal concurrency, the number of threads competing for a single variable is reduced, which in disguise reduces the amount of concurrency competing for shared resources. When multiple threads are competing for the same atomic variable,

If the failure is not a spin-CAS retry, it attempts to obtain a lock on the other atomic variable, and finally, when the current value is fetched, the value of all variables is added and the value of base is returned.

Longadder maintains the array of atomic updates to delay initialization and the size of a base-value variable base array is 2 of the N-square size, and the subscript of the array table is represented by the mask of the hashcode value of each thread, and the variable entity inside the array is the cell type.

The Cell type is an improvement of the atomic, which is used to reduce the contention of the cache, which is wasteful for most atomic operation Byte fills, because atomic operations are scattered in memory in an irregular, multi-atomic operation with no contact with one another. But atomic array elements that are stored next to each other can often share cache rows, or pseudo-shares. So this is an improvement in performance.

In addition, because cells occupy memory is relatively large, so it is not created at first, but when needed to create, that is, lazy loading, when there is no space at the beginning, all updates are the operation of the base variable.

The following is a simple analysis of Longadder code

Here I simply introduce the implementation of the Code, detailed implementation, we can look at the code to study. In order to reduce high concurrency under a variable CAS contention failure after a large number of threads spin to reduce concurrency performance issues, longadder internally by maintaining multiple cell elements based on the amount of concurrent requests (a dynamic cell array) to share the contention for resources for a single variable.

First, let's look at Longadder's structural class diagrams, such as:

You can see that Longadder inherits from the Striped64 class, STRIPED64 internal maintenance of three variables, Longadder real value is actually the value of the base and cell array all the cell element value of the accumulation, base is a base value, the default is 0, Cellbusy is used to implement spin locks, which are used to synchronize threads when creating cell elements or expanding the cell array.

Next go into the source code such as see cell structure, the source code as follows:

@sun. misc.contendedStaticFinalclassCell {volatile Longvalue; Cell (LongX) {value =x;} Final Boolean cas (LongCmpLongval) {            returnUnsafe.compareandswaplong ( This, Valueoffset, CMP, Val); }        //Unsafe Technology        Private Staticfinal Sun.misc.Unsafe Unsafe; Private StaticFinalLongValueoffset; Static {            Try{UNSAFE=Sun.misc.Unsafe.getUnsafe (); Class<?> ak = Cell.class; Valueoffset=Unsafe.objectfieldoffset (Ak.getdeclaredfield ("value")); } Catch(Exception e) {Throw NewError (e); }        }    }

As the above code knows, the cell's construction is simple, internally maintaining a variable that declares volatile, which is declared volatile because the thread is manipulating the value variable when the lock is not used, in order to ensure that the memory visibility of the variable is only declared volatile. And here's what the previous file says about using the unsafe class to set value

Next enter the source code of Longadder to see a few important methods, as follows:

1.long sum () method: Returns the current value, the internal operation is to accumulate all the values inside the cell value after the base, the following code, because the calculation of the sum of the cell array is not locked, so in the accumulation process may have other threads in the cell value has been modified, there are It is possible for the array to be expanded, so the value returned by sum is not very precise,

The return value is not an atomic snapshot value when the Sum method is called.

The source code is as follows:

  

 Public Longsum () {cell[] as=cells;        Cell A; Longsum =Base; if( as!=NULL) {             for(inti =0; I < as. length; ++i) {if((A = as[i])! =NULL) Sum+=A.value; }        }        returnsum;}

2.void Reset () method: Reset operation, the following code to set base 0, if the Cell array has elements, the element value is reset to 0. The source code is as follows:

  

 Public voidReset () {cell[] as=cells;        Cell A; Base=0L; if( as!=NULL) {             for(inti =0; I < as. length; ++i) {if((A = as[i])! =NULL) A.value=0L; }        }   }

3.long Sumthenreset () method: is the modified version of Sum, the following code, after calculating the sum of the corresponding cell value, reset the current cell value to 0,base reset to 0. There is a problem when multithreading calls this method, such as considering that the first calling thread empties the value of the Cell, and that the next thread is incremented when it is called 0 values.

The source code is as follows:

  

 Public LongSumthenreset () {cell[] as=cells;        Cell A; Longsum =Base; Base=0L; if( as!=NULL) {             for(inti =0; I < as. length; ++i) {if((A = as[i])! =NULL) {sum+=A.value; A.value=0L; }            }        }        returnsum; }

4.long Longvalue () is equivalent to sum (), the source code is as follows:

  

     Public Long Longvalue () {        returnthis. sum ();    }

5.void Add (long x) increments the X-to-atom variable, and the process is atomic. The source code is as follows:

  

 Public voidAddLongx) {cell[] as;Longb, V;intm;        Cell A; if(( as= cells)! =NULL|| !casbase (b =Base, B + x)) {//(1)Boolean uncontended =true; if( as==NULL|| (M = as. Length-1) <0||//(2)(A = as[Getprobe () & M]) ==NULL||//(3)! (uncontended = A.cas (v = a.value, V + x)))//(4)Longaccumulate (x,NULL, uncontended);//(5)}} Final Boolean casbase (LongCmpLongval) {        returnUnsafe.compareandswaplong ( This, BASE, CMP, Val); }

You can see the code above, when the first thread a executes add, the code (1) executes the Casbase method, the base is set to X through the CAS, and if successful it returns directly, the value of base is 1.

If multiple threads execute add at the same time, while executing to casbase, only one thread a succeeds, and the other thread executes the code (2) because of CAS failure, the code (2) is the length of the cells array, and if the array length is 0, the code (5) is executed, otherwise the cells are not 0 in length. Shows that the cells array has elements that execute the code (3),

The Code (3) calculates the current thread's subscript in the array first, then gets the cell value corresponding to the current thread, and if it does (4) performs the CAS operation, the CAS fails the code (5).

Code (5) is specific to the expansion and initialization of the array, this code is more complex, here is not explained, interested can go inside to see.

Two. Longaccumulator Type source Analysis

Longadder class is a special case of Longaccumulator, Longaccumulator provides a more powerful function than Longadder, the following constructor, where Accumulatorfunction is a binocular operator interface, Returns a computed value based on the two parameters entered, and the identity is the initial value of the Longaccumulator accumulator.

 public   Longaccumulator ( Longbinaryoperator accumulatorfunction,  long   identity)        {  accumulatorfunction;  base  = this . Identity = identity;}  public  interface   Longbinaryoperator { //  Returns a value based on two parameters  long  Applyaslong (long
     left, long   

The above mentioned Longadder is actually a special case of longaccumulator, call Longadder quite use the following way to call Longaccumulator.

New Longadder ();     New Longaccumulator (new  longbinaryoperator () {        @Override        publiclong Applyaslong (longlong right ) {            return left + right ;        }     0);

Longaccumulator can provide an accumulator initial non-0 value compared to Longadder, the latter can only default to 0, the former may also specify the accumulation rules, such as not cumulative and multiply, only need to construct longaccumulator when the custom binocular operator can be passed, The latter incorporates cumulative rules.

It is known from the following code that the difference between Longaccumulator and Longadde is Casbase, the latter passing b+x, while the former is called R=function.applyaslong (b=base.x).

The Longadder class add source code is as follows:

 Public voidAddLongx) {cell[] as;Longb, V;intm;        Cell A; if(( as= cells)! =NULL|| !casbase (b =Base, B +x) {Boolean uncontended=true; if( as==NULL|| (M = as. Length-1) <0||(A= as[Getprobe () & M]) ==NULL|| ! (uncontended = A.cas (v = a.value, V +x)) longaccumulate (x,NULL, uncontended); }    }

The source code of Longaccumulator's accumulate method is as follows:

 Public voidAccumulate (Longx) {cell[] as;LongB, V, R;intm;        Cell A; if(( as= cells)! =NULL||(R= Function.applyaslong (b =Base, x))! = B &&!Casbase (b, R)) {Boolean uncontended=true; if( as==NULL|| (M = as. Length-1) <0||(A= as[Getprobe () & M]) ==NULL|| ! (uncontended =(R= Function.applyaslong (v = a.value, x)) = = V | |A.cas (V, R)))        Longaccumulate (x, function, uncontended); }    }

In addition Longaccumulator call Longaccumulate when the function is passed, and Longadder is null, from the following code can know when FN is null, the time is to use the v+x addition operation, This is equivalent to LONGADDER,FN is not NULL when the transfer of the FN function is calculated, if FN is an addition is equivalent to Longadder;

Else if Base null) ? V + X:fn.applyaslong (V, x)       ))// Fall back on using base
      Break

Longadder of Java concurrent programming and Longaccumulator source code exploration

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.