The atomic variables and volatile of Java concurrency

Source: Internet
Author: User
Tags prev

We know that in concurrent programming, when multiple threads share a variable or object, they must be synchronized. Synchronization consists of two layers:1) mutually exclusive access, 2) visibility , that is, multiple threads are mutually exclusive access to shared variables, and the thread's modifications to shared variables must be visible to other threads, that is, all threads are accessing the most recent values.

1. Volatile variables and references

The effect of volatile is to ensure visibility, but without mutually exclusive access semantics. Volatile guarantees the visibility of its decorated references and the objects it references, and volatile not only guarantees the visibility of variables or references to all threads that access it, but also guarantees the visibility of the objects it references to all the threads that access it. The use of volatile requires that the following two conditions are met :

1) Read and write operations on variables or references do not depend on the current value of the variable or reference (if only a specific individual thread modifies the shared variable, the modification can also depend on the current value);

2) The change quantity or the reference is not included in other invariant conditions;

The most common error scenario for volatile is the use of volatile to implement concurrent i++; The reason for the error is that the operation relies on the current value of the I variable, which is based on the current value of the I variable, so that he relies on the current value of I. multiple threads execute i++; Updates are lost. For example, two threads read the current value of I 8, all to add one, and then write back, and finally I the result is 9, rather than we expect 10, lost the update. Then the introduction of atomic variable is aimed at this flaw of volatile!!! The modification of an atomic variable allows it to rely on the current value, so the word "atomic variable" is slightly more reinforcing than the semantics of volatile! Not only does he have volatile visibility, but changes to the atomic variable can depend on the current value .

2. Atomic variables and atomic references

Atomic variables and atomic references are introduced starting with Java 1.5:

Java.util.concurrent.atomic.AtomicBoolean

Java.util.concurrent.atomic.AtomicInteger

Java.util.concurrent.atomic.AtomicLong

Java.util.concurrent.atomic.AtomicReference

and their corresponding arrays:

Java.util.concurrent.atomic.AtomicIntegerArray

Java.util.concurrent.atomic.AtomicLongArray

Java.util.concurrent.atomic.AtomicReferenceArray

Atomic variables and references are implemented using Compareandswap (CAS directives): atoms that depend on the current value are modified. And they are implemented using both volatile and unsafe,volatile guarantees visibility, and unsafe guarantees atomicity . We can slightly analyze the source code of Atomicreference:

 Public classAtomicreference<v>Implementsjava.io.Serializable {Private Static Final LongSerialversionuid = -1848883965231344442l; Private Static Finalunsafe unsafe =Unsafe.getunsafe (); Private Static Final LongValueoffset; Static {        Try{Valueoffset=Unsafe.objectfieldoffset (atomicreference.class. Getdeclaredfield ("value")); } Catch(Exception ex) {Throw NewError (ex);} }    Private volatileV value; /*** Creates a new atomicreference with the given initial value. *     * @paramInitialValue the initial value*/     Publicatomicreference (V initialvalue) {value=InitialValue; }    /*** Creates a new atomicreference with null initial value. */     Publicatomicreference () {}/*** Gets the current value. *     * @returnThe current value*/     Public FinalV Get () {returnvalue; }    /*** Sets to the given value. *     * @paramnewvalue the new value*/     Public Final voidset (V newvalue) {value=NewValue; }    /*** Eventually sets to the given value. *     * @paramNewValue The new value *@since1.6*/     Public Final voidLazyset (V newvalue) {unsafe.putorderedobject ( This, Valueoffset, NewValue); }    /*** atomically Sets the value to the given updated value * If the current value {@code= =} The expected value. * @paramexpect the expected value *@paramUpdate the new value *@return {@codetrue} if successful.     False return indicates that * the actual value is not equal to the expected value. */     Public Final BooleanCompareandset (v expect, v update) {returnUnsafe.compareandswapobject ( This, Valueoffset, expect, update); }    /*** atomically Sets the value to the given updated value * If the current value {@code= =} The expected value. * * <p><a href= "Package-summary.html#weakcompareandset" >may fail * spuriously and does not provide ORD Ering Guarantees</a>, so was * only rarely a appropriate alternative to {@codeCompareandset}. *     * @paramexpect the expected value *@paramUpdate the new value *@return {@codetrue} if successful*/     Public Final BooleanWeakcompareandset (v expect, v update) {returnUnsafe.compareandswapobject ( This, Valueoffset, expect, update); }    /*** atomically sets to the given value and returns the old value. *     * @paramNewValue The new value *@returnThe previous value*/@SuppressWarnings ("Unchecked")     Public Finalv Getandset (v newvalue) {return(V) Unsafe.getandsetobject ( This, Valueoffset, NewValue); }    /*** atomically updates the current value with the results of * applying the given function, returning the Previ OUs value. The * function should is side-effect-free, since it May is re-applied * When attempted updates fail due to content     Ion among threads. *     * @paramupdatefunction a side-effect-free function *@returnThe previous value *@since1.8*/     Public FinalV Getandupdate (unaryoperator<v>updatefunction)        {V prev, next;  Do{prev=get (); Next=updatefunction.apply (prev); }  while(!Compareandset (prev, next)); returnprev; }......

We can see the use of: private volatile V value, to ensure the visibility of value;

While

Private static final unsafe unsafe = unsafe.getunsafe ();
Private static final long valueoffset;

static {
try {
Valueoffset = Unsafe.objectfieldoffset
(AtomicReference.class.getDeclaredField ("value"));
} catch (Exception ex) {throw new Error (ex);}
}

This code means: Get the Value property of the Atomicreference<v> instantiated object in the Valueoffset position of the change object in the heap memory, and:

Unsafe.compareandswapobject (this, valueoffset, expect, update);

The function is to compare the value of the memory at Valueoffset to whether it is expect, and then replace it with the new value update, the operation is atomic. So volatile guarantees visibility, and unsafe guarantees atomicity. The source of Unaryoperator,binaryoperator and so on is obviously imitation C + +, because there is no function pointer in Java, so can only use a unary, two-dollar operation object to achieve the corresponding function.

3. Unsafe

Unsafe source code can be found in:http://www.docjar.com/html/api/sun/misc/Unsafe.java.html

His implementation is mainly through the compiler, using some of the CPU's atomic instructions to achieve.

 This class is very low-level, and correspond to asmall number of hardware instructions (on typical machines). 
    
     compilersare encouraged to optimize these methods accordingly.
    

4. Longadder (Adder)

In the JDK In 1.8, a fully optimized atom variable is introduced: Java.util.concurrent.atomic.LongAdder, whose performance is best compared to other atomic variables and volatile variables, so do not use other atomic variables where you can use Longadder. However, Longadder does not provide an operation that relies on the value of the current variable to modify. Generally, it is best to implement concurrency counters.

The Longadder implements the following interfaces:

 Public voidAddLongx);//plus x Public voidIncrement ();//plus 1 Public voidDecrement ();//minus 1 Public LongSUM ();//sum Public voidReset ();//Reset 0 PublicString toString () {returnlong.tostring (sum ()); }    /*** equivalent to {@link#sum}. *     * @returnThe sum*/     Public LongLongvalue () {returnsum (); }    /*** Returns the {@link#sum} as an {@codeint} After a narrowing * primitive conversion. */     Public intintvalue () {return(int) sum (); }    /*** Returns the {@link#sum} as a {@codeFloat} * After a widening primitive conversion. */     Public floatFloatvalue () {return(float) sum (); }    /*** Returns the {@link#sum} as a {@codeDouble} After a widening * primitive conversion. */     Public DoubleDoublevalue () {return(Double) sum (); }

The atomic variables and volatile of Java concurrency

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.