Java since JDK1.5 provides Java. Util. Concurrent. Atomic package, convenient programmers in a multithreaded environment, unlocked for atomic operations. The underlying atomic variable uses the atomic instructions provided by the processor, but different CPU architectures may provide different atomic instructions, and some form of internal locking may be required, so this method cannot absolutely guarantee that the thread is not blocked. The ###Atomic package is a small toolkit that supports lockless thread-safe programming on a single variable.

The Atomic update base type class is used to update base types atomically. The Atomic package provides the following three classes:

  • AtomicBoolean: Atom updates Boolean type.
  • AtomicInteger: Atom update integer.
  • AtomicLong: Atom updates long integers.

Common AtomicInteger methods are as follows:

  • Int addAndGet(int delta) : Atomically adds the input value to the value in the instance (the value in the AtomicInteger) and returns the result
  • Boolean compareAndSet(int expect, int update) : If the value entered is equal to the expected value, set it to the input value atomically.
  • Int getAndIncrement() : atomically increments the current value by 1.
  • Void lazySet(int newValue) : eventually set to newValue. Using lazySet may cause other threads to read the old value for a short time. More information about this method can be found in the article “How does AtomicLong. LazySet Work?” translated by Befa.
  • Int getAndSet(int newValue) : The value set atomically to newValue and returns the old value.

# # # # # AtomicInteger instance

package com.thread.atomic;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by Fant.J.
 * 2018/2/28 17:21
 */
public class AtomicIntegerTest {
    static AtomicInteger value = new AtomicInteger(0);

    public static int getValue() {returnvalue.getAndIncrement(); //value++; } public static void main(String[] args) { /* Runnable r1 = ()->{for(;;) { System.out.println(Thread.currentThread().getName()+":"+getValue()); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }}}; r1.run(); */ new Thread(()->{for(;;) { System.out.println(Thread.currentThread().getName()+":"+getValue());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(()->{
            for(;;) { System.out.println(Thread.currentThread().getName()+":"+getValue()); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }}Copy the code

Lambda expressions, they don’t understand can read my article: https://www.jianshu.com/p/3a08dc78a05f

For dessert

The Atomic package provides Atomic updates of three basic types, but Java’s basic types also include char, float, and double. So the question is, how do atoms update the other basic types? Unsafe only provides three CAS methods, such as compareAndSwapObject, for instance. CompareAndSwapInt and compareAndSwapLong, again see AtomicBoolean source, found that it is the first Boolean converted to integers, again using compareAndSwapInt for CAS, So atomic double updates can be done in a similar way.

The Atomic update array class updates an element in an array atomically. The Atomic package provides the following three classes:

  • AtomicIntegerArray: Atom updates the elements of an integer array.

  • AtomicLongArray: Atom updates elements in a long integer array.

  • AtomicReferenceArray: The atom updates the element in the array of reference types.

  • The AtomicIntegerArray class provides an atomic way to update an array of integers

  • Int addAndGet(int I, int delta) : Atomically adds the input value to the elements of the array index I.

  • Boolean compareAndSet(int I, int expect, int UPDATE) : Atomically set the element at position I to update if the current value is equal to the expected value.

Example:

Public class AtomicIntegerArrayTest {static int[] value = new int[]{1,2}; static AtomicIntegerArray ai = new AtomicIntegerArray(value); Public static void main(String[] args) {ai.getandset (0,3); System.out.println(ai.get(0)); }}Copy the code

AtomicInteger updates the base type AtomicInteger. Only one variable can be updated. If you want to update multiple variables atomically, you need to use this atom to update the class provided by the reference type. The Atomic package provides the following three classes:

AtomicReference: Atomic update reference type. AtomicReferenceFieldUpdater: atomic updates a reference type in the field. AtomicMarkableReference: Atom updates reference types with marker bits. You can atomically update a Boolean marker bit and reference type. The constructor is AtomicMarkableReference(V initialRef, Boolean initialMark)

The code for AtomicReference is as follows:

package com.thread.atomic;

import java.util.concurrent.atomic.AtomicReference;

/**
 * Created by Fant.J.
 * 2018/2/28 18:40
 */
public class AtomicReferenceTest {
    static AtomicReference<User> ar = new AtomicReference<>();

    public static void main(String[] args) {
        User user = new User("fantj", 20); User updateUser = new User("dalao", 20); ar.set(user); ar.compareAndSet(user,updateUser); //public final boolean compareAndSet(User expect, User update) System.out.println(ar.get().getName() +":"+ar.get().getAge());
    }


    static class User{
        private String name;

        private Integer age;

        public User(String name, int i) {
            this.name = name;
            this.age=i;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) { this.age = age; }}}Copy the code

If we only need a field from a class, then we need to use Atomic update fields. The Atomic package provides the following three classes:

  • AtomicIntegerFieldUpdater: atomic updates integer field updater.
  • AtomicLongFieldUpdater: A updater that atomically updates long integer fields.
  • AtomicStampedReference: Atom updates a reference type with a version number. This class associates integer values with references and can be used for additional data of atoms and version numbers of the data, solving ABA problems that may occur when atomic updates are made using CAS.

Atomic update field classes are abstract classes, and each time they are used a updater must be created using the static method newUpdater. The public volatile modifier must be used for fields of the atomically updated class.

AtomicIntegerFieldUpdater example code is as follows:

package com.thread.atomic; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; /** * If we need only a field from a class, we need to use the atomic update field class. * Created by Fant. J. * 2018/2/28 18:50 * / public class AtomicIntegerFieldUpdaterTest {/ / assume that we need the age attribute in the User, And to the age of atomic updates the static AtomicIntegerFieldUpdater < User > aif = AtomicIntegerFieldUpdater. NewUpdater (User. The class,"age");

    public static void main(String[] args) {
        User user = new User("fantj", 20); Aif. getAndIncrement(User); System.out.println(aif.get(user)); } static class User{ private String name; public volatile int age; Volatile public User(String name, int I) {this.name = name; this.age=i; } public StringgetName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) { this.age = age; }}}Copy the code

So finally, let’s solve the CAS puzzle

##### What is CAS

CAS: Compare and Swap. The java.util.Concurrent package uses CAS to implement an optimistic lock as opposed to synchronized. Optimistic locking means that every time you go to fetch data, you are optimistic that the data will not be modified, so you will not lock the data, but during the update, you will determine whether the data has been updated during the period. CAS has three operands: the memory value V, the old expected value A, and the new value B to modify. Change the memory value V to B if and only if the expected value A and memory value V are the same, otherwise nothing is done. The key point of CAS is that the atomicity of the comparison-and-swap operation is guaranteed at the hardware level. The processor implements atomic operations between multiple processors based on cache locking or bus locking.

###### Advantages and disadvantages of CAS

  • CAS is very efficient because it is atomicity at the hardware level and does not lock the current thread.

  • CAS implements atomic manipulation efficiently, but it still has three problems.

    1. ABA problem. The CAS checks whether the value has changed. If the value has not changed, the CAS updates the value. But if A value is A, changes to B, and then changes to A, then CAS checks that the value hasn’t changed, when in fact it has. The solution to the ABA problem is to use version numbers. Append the version number to the variable, increment the version number by one each time the variable is updated, so a-b-a becomes 1a-2b-3a. Since Java1.5, the JDK atomic package has provided a class AtomicStampedReference to address ABA issues.

    2. The higher the concurrency, the more times the CAS fails. If the CAS fails for a long time, the CPU cost will be greatly increased. Therefore, CAS is not suitable for scenarios where there is a lot of competition.

    3. Atomic operations of only one shared variable are guaranteed. When operating on multiple shared variables, CAS cannot guarantee atomicity of the operation and can be used to lock or combine multiple shared variables into a single shared variable. Let’s say we have two shared variables I =2,j=a, combine ij=2a, and then use CAS to manipulate ij. Since Java1.5, the JDK has provided the AtomicReference class to ensure atomicity of reference objects. You can place multiple variables in an object to perform CAS operations.

This is a brief introduction to the most commonly used atomic classes, but you can explore the rest for yourself if you are interested. The official documentation

References: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html http://ifeve.com/java-atomic/