Atomic manipulation classes in Java

Source: Internet
Author: User
Tags cas

Reprint: "The Art of Ava Concurrent Programming" chapter 7th

When a program updates a variable, if multiple threads update this variable at the same time, it is possible to get a value other than expected, such as the variable i=1,a thread update i+1,b thread also updates i+1, after two thread operation may I not equal 3, but equal to 2. Because the A and B threads get the i in the update variable i is 1, this is the thread unsafe update operation, usually we will use synchronized to solve this problem, synchronized will ensure that multithreading does not update the variable i.

While Java provides the Java.util.concurrent.atomic package (hereinafter referred to as the atomic package) from JDK 1.5, the atomic operations class in this package provides a simple, efficient, and thread-safe way to update a variable.

Because there are many types of variables, there are also many classes available in the atomic package, roughly 4 types of atomic update methods, namely atomic Update primitives, Atomic update arrays, atomic update references, and Atomic update properties (fields). The classes in the atomic package are basically wrapper classes that are implemented using unsafe.

Atomic Update Basic Type

By updating the base type atomically, the atomic package provides the following 3 classes.

    • Atomicboolean: Atomic Update Boolean type.
    • Atomicinteger: Atomic update integral type.
    • Atomiclong: Atomic update long type.

The methods provided in the above 3 classes are almost identical, so this section only takes Atomicinteger as an example, and the common methods of Atomicinteger are as follows:

    • int addandget (int delta): atomically adds the input value to the value in the instance (value in Atomicinteger) and returns the result.
    • Boolean compareandset (int expect,int update): If the entered value is equal to the expected value, the value is atomically set to the value entered.
    • int getandincrement (): atomically adds 1 to the current value, note that this returns the value before the increment.
    • int getandset (int newvalue): atomically sets the value to NewValue and returns the old value.
    • void Lazyset (int newvalue): Eventually set to NewValue, using Lazyset setting the value may cause other threads to read the old value for a short period of time. More information on this method can be found in the translation of the Concurrent Programming network, "How does the Atomiclong.lazyset work?" 》。
    • int getandset (int newvalue): atomically sets the value to NewValue and returns the old value

Atomicinteger Example:

new AtomicInteger();System.out.println(atomicInteger.getAndIncrement());

So how does the getandincrement implement atomic operations? Let us analyze its implementation principle together, the source code of Getandincrement is as follows:

publicfinalintgetAndIncrement() {    return unsafe.getAndAddInt(this1);}publicfinalintgetAndAddIntlongint var4) {    int var5;    do {        this.getIntVolatile(var1, var2);    while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));    return var5;}

First we look at the getAndIncrement method, it is simply a simple packaging of unsafe class, the specific logic is in the unsafe. Looking at the getAndAddInt method, the method first obtains the VAR2 value in the this.getIntVolatile(var1, var2); memory address that var1 points to, this is to get the old value, and then update the value to VAR5+VAR4 by CAS, and the update failure goes to self-tracking.

The atomic package provides 3 basic types of atomic updates, but there are also char, float, and double in the basic Java type. So the question comes, how does the atom update other basic types? The class in the atomic package is basically implemented using unsafe, let's look at the source of unsafe.

/*** If the current value is expected, the atom updates the Java variable to x* @returnreturns True if the update succeeds*/ Public Final native Boolean Compareandswapobject(Object O,LongOffset, object expected, object x); Public Final native Boolean Compareandswapint(Object O,LongOffset,intExpected,intx); Public Final native Boolean Compareandswaplong(Object O,LongOffset,LongExpected,Longx);

Through the code, we found that unsafe only provides 3 CAs methods: Compareandswapobject, Compareandswapint and Compareandswaplong, and then see Atomicboolean source Code, Discover that it is the first to convert a Boolean into an integer
Type, and then use Compareandswapint for CAs, so atomic updates char, float, and double variables can also be used with similar
Ideas to achieve.

//Atomicboolean Public Final Boolean Compareandset(BooleanExpectBooleanUpdate) {intE = expect?1:0;intu = update?1:0;returnUnsafe.Compareandswapint( This, Valueoffset, E, u);}//Atomicdouble Public Final Boolean Compareandset(DoubleExpectDoubleUpdate) {returnUpdater.Compareandset( This, Double.doubletorawlongbits(expect), Double.doubletorawlongbits(update));}
Atomic Update Array

To update an element in an array by atomic means, the atomic package provides 4 classes:

    • Atomicintegerarray: Atoms update elements in an integer array.
    • Atomiclongarray: Atoms update elements in an array of long integers.
    • Atomicreferencearray: An atom updates an element in an array of reference types.

The above-mentioned classes provide almost the same approach, we use the Atomicintegerarray class as an example, its common methods are as follows:

    • int addandget (int i, int delta): atomically adds the input value to the element of index i in the array.
    • Boolean compareandset (int i, int expect, int update): atomically sets the element of the array position I to the update value if the current value equals the expected value.
staticintnewint12 };staticnew AtomicIntegerArray(value);publicstaticvoidmain(String[] args) {        ai.getAndSet(0,3);        System.out.println(ai.get(0));        System.out.println(value[0]);}

Output connection Result:

31

It is important to note that the array value is passed through the construction method, and then Atomicintergerarray copies the current array, so when Atomicintergerarray modifies the inner array elements, the incoming array is not affected.

Construction Method:

/** * Creates a new AtomicIntegerArray with the same length as, and * all elements copied from, the given array. * * @param array the array to copy elements from * @throws NullPointerException if array is null */public AtomicIntegerArray(int[] array) {    // Visibility guaranteed by final field guarantees    this.array = array.clone();}
Atomic Update Reference type

Atomic Update primitive type Atomicinterger, only one variable can be updated, if you want to update more than one variable, you need to use this atom to update the class provided by the reference type. The atomic package provides the following 3 classes:

    • Atomicreference: Atomic Update Reference type
    • Atomicreferencefieldupdater: Atom updates a field in a reference type.
    • Atomicmarkablereference: Atom updates A reference type with a tag bit. Can atomically update the token bit and reference type of a Boolean type. The construction method is Atomicmarkablereference (V Initialref,boolean initialmark).

The above classes provide almost the same approach, so here we only take atomicreference as an example, the use of the Atomicreference example code is as follows:

 Public StaticAtomicreference<user> Atomicuserref =NewAtomicreference<user> (); Public Static void Main(string[] args) {User User =New User("Conan", the); Atomicuserref.Set(user); User UpdateUser =New User("Shinichi", -); Atomicuserref.Compareandset(user, UpdateUser); System. out.println(Atomicuserref.Get().GetName()); System. out.println(Atomicuserref.Get().Getold());}Static classUser {PrivateString name;Private intOld Public User(String name,intOld) { This.name= name; This. Old= old; } PublicStringGetName() {returnName } Public int Getold() {returnOld }}
// 运行结果Shinichi17

The principle of its implementation depends on the unsafe.compareAndSwapObject method.

publicfinalbooleancompareAndSet(V expect, V update) {    return unsafe.compareAndSwapObject(this, valueOffset, expect, update);}
Atom Update Field Class

If you want to atomically update a field in a class, you need to use an Atom Update field class, the atomic package provides the following 3 classes for atomic field updates.

    • Atomicintegerfieldupdater: An update to the field of an atomic update integer.
    • Atomiclongfieldupdater: atomically updates the updater of the long field.
    • Atomicstampedreference: Atom updates A reference type with a version number. This class associates an integer value with a reference and can be used to update data and version numbers of the atom, which resolves an ABA problem that may occur when using CAs for atomic updates.

It takes two steps to update the field class atomically. First, because the Atomic Update field classes are abstract classes, you must create an update using the static method Newupdater () each time you use it, and you need to set the classes and properties that you want to update. In the second step, the field (property) of the update class must use the public volatile modifier.

The above 3 classes provide almost the same approach, here only astomicintegerfieldupdater as an example, the Astomicintegerfieldupdater sample code is as follows:

//Create Atomic Updater and set properties of object classes and objects that need to be updatedPrivate StaticAtomicintegerfieldupdater<user> a = Atomicintegerfieldupdater.Newupdater(User.class,"Old"); Public Static void Main(string[] args) {//Set Conan's age to be 10 years oldUser Conan =New User("Conan",Ten);//Conan grew one year old, but still output old ageSystem. out.println(A.getandincrement(Conan));//Output Conan's age nowSystem. out.println(A.Get(Conan));} Public Static classUser {PrivateString name; Public volatile intOld Public User(String name,intOld) { This.name= name; This. Old= old; } PublicStringGetName() {returnName } Public int Getold() {returnOld }}

The results of the operation are as follows:

1011

Atomic manipulation classes in Java

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.