Use of atomic classes

I. Overview

java.util.concurrent.atomicThe package provides us with a series of thread-safe, simple-to-use atomic operation classes for updating variables. Atomic classes are based on CAS algorithm to achieve thread safety, no need to lock, and high performance.

Compare the effect of AtomicInteger atomic class and int class:

package package05_atomic;

import java.util.concurrent.atomic.AtomicInteger;

class Compare {
    
    
    //默认初始值为1
    private AtomicInteger AI = new AtomicInteger();
    private void addValue() {
    
    
        for (int i = 0; i < 5; i++) {
    
    
            int value = AI.addAndGet(1);
            System.out.println(Thread.currentThread().getName()+":"+value);
        }
    }

     public static void main(String[] args) {
    
    
         Compare demo = new Compare();
         new Thread(demo::addValue,"线程一").start();
         new Thread(demo::addValue,"线程二").start();
     }
}

Insert picture description here

package package05_atomic;

class Compare {
    
    

    private Integer value = 1;
    private void addValue() {
    
    
        for (int i = 0; i < 5; i++) {
    
    
            ++value;
            System.out.println(Thread.currentThread().getName()+":"+value);
        }
    }

     public static void main(String[] args) {
    
    
         Compare demo = new Compare();
         new Thread(demo::addValue,"线程一").start();
         new Thread(demo::addValue,"线程二").start();
     }
}

Insert picture description here
The result was confusion when the atomic class was not used. This is because ordinary data types cannot guarantee ++ithe atomicity of such operations, which leads to confusion.

2. Common atomic classes

Atomic operation classes can be divided into five types: basic data type atomic classes, array type atomic classes, reference type atomic classes, object attribute modification types, and high-performance atomic classes .

(1) Basic data type atomic class

Take for AtomicIntegerexample:

package package05_atomic;

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerTest {
    
    
    public static void main(String[] args) {
    
    
        AtomicInteger i = new AtomicInteger(0);
// 获取并自增
        System.out.println(i.getAndIncrement());
// 自增并获取
        System.out.println(i.incrementAndGet());
// 获取并加值
        System.out.println(i.getAndAdd(5));
// 加值并获取
        System.out.println(i.addAndGet(-5));
// 获取并更新
        System.out.println(i.getAndUpdate(p -> p - 2));
// 更新并获取
        System.out.println(i.updateAndGet(p -> p + 2));
// 获取并计算
        System.out.println(i.getAndAccumulate(10, (p, x) -> p + x));
// 计算并获取
        System.out.println(i.accumulateAndGet(-10, (p, x) -> p + x));
    }
}

(2) Array type atomic class

Take for AtomicIntegerArrayexample:

public final int get(int i) //获取 index=i 位置元素的值
public final int getAndSet(int i, int newValue)//返回 index=i 位置的当前的值,并将其设置为新值:newValue
public final int getAndIncrement(int i)//获取 index=i 位置元素的值,并让该位置的元素自增
public final int getAndDecrement(int i) //获取 index=i 位置元素的值,并让该位置的元素自减
public final int getAndAdd(int delta) //获取 index=i 位置元素的值,并加上预期的值
boolean compareAndSet(int expect, int update) //如果输入的数值等于预期值)(比较的是引用地址),则以原子方式元素值设置为输入值
public final void lazySet(int i, int newValue)//最终 将index=i 位置的元素设置为newValue,使用 lazySet 设置之后可能导致其他线程在之后的一小段时间内还是可以读到旧的值。

(3) Reference type atomic class

The reference type atomic class is used to atomically update multiple variables (objects). Take for AtomicReferenceexample:

package package05_atomic;

import java.util.concurrent.atomic.AtomicReference;

class Person {
    
    
    private String name;
    private int age;

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

    @Override
    public String toString() {
    
    
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

class AtomicReferenceTest {
    
    
    public static void main(String[] args) {
    
    
        AtomicReference<Person> atomicReference = new AtomicReference<Person>();
        Person person = new Person("曹孟德",62);
        atomicReference.set(person);
        System.out.println(atomicReference.get().toString());

        Person newperson = new Person("郭奉孝",37);
        atomicReference.compareAndSet(person,newperson);
        System.out.println(atomicReference.get().toString());
    }
}

: The ABA problem may occur when multiple variables are assigned atomically: the Insert picture description here
solution is to add version number information when each thread assigns values ​​to variables.

(4) Modification type of the attributes of the object

This type is used to atomically update a certain field in a certain class.
Take for AtomicReferenceFieldUpdateexample:

package package05_atomic;

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

class Student {
    
    
    public volatile String name;

    @Override
    public String toString() {
    
    
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}

class FieldUpdate {
    
    
    public static void main(String[] args) {
    
    
        Student student = new Student();
        AtomicReferenceFieldUpdater arfu = AtomicReferenceFieldUpdater.newUpdater(Student.class, String.class, "name");
        arfu.compareAndSet(student, null, "诸葛孔明");
        System.out.println(student);
    }
}

注意: Object attribute modification types are abstract classes , so before using it, you must use the static method newUpdater to create a new updater, and then pass the parameters to the class and attribute that need to be updated, and the attribute name . At the same time, the attributes to be modified must be modified with the public volatile keyword .

(5) High-performance atom class (atomic accumulator)

There are four types of atomic accumulators as follows:
DoubleAccumulator
DoubleAdder
LongAccumulator
LongAdder

Taking LongAdder as an example, the purpose of introduction is to solve the spin bottleneck problem of AtomicLong in a high-concurrency environment.
思想概述: Using the idea of ​​segmentation , the value value is scattered into an array, different threads will hit different slots of the array, each thread only performs CAS operations on the value in its own slot, and finally adds the values ​​of these segments Get the final value.

Guess you like

Origin blog.csdn.net/m0_46550452/article/details/107457918