アトミッククラスの使用

I.概要

java.util.concurrent.atomicこのパッケージは、変数を更新するための一連のスレッドセーフで使いやすいアトミック操作クラスを提供します。アトミッククラスはCASアルゴリズムに基づいており、スレッドセーフ、ロックの必要性、および高性能を実現します。

AtomicIntegerアトミッククラスとintクラスの効果を比較します。

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();
     }
}

ここに写真の説明を挿入

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();
     }
}

ここに写真の説明を挿入
その結果、アトミッククラスが使用されなかったときに混乱が生じました。これは、通常のデータ型++iではそのような操作のアトミック性を保証できず、混乱を招くためです。

2.一般的なアトミッククラス

アトミック操作クラスは、基本データ型アトミッククラス、配列型アトミッククラス、参照型アトミッククラス、オブジェクト属性変更タイプ、および高性能アトミッククラスの5つのタイプに分類できます

(1)基本データ型アトミッククラス

AtomicIntegerたとえば、次のようにします。

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)配列型アトミッククラス

AtomicIntegerArrayたとえば、次のようにします。

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)参照型アトミッククラス

参照型のアトミッククラスは、複数の変数(オブジェクト)をアトミックに更新するために使用されます。AtomicReferenceたとえば、次のようにします。

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());
    }
}

:複数の変数がアトミックに割り当てられている場合、ABA問題が発生する可能性があります:ここに写真の説明を挿入
解決策は、各スレッドが変数に値を割り当てるときにバージョン番号情報を追加することです。

(4)オブジェクトの属性の変更タイプ

このタイプは、クラスのフィールドアトミックに更新するために使用されます。たとえば
、次のAtomicReferenceFieldUpdateようにします。

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);
    }
}

注意:オブジェクト属性の変更タイプは抽象クラスであるため、静的メソッドnewUpdaterを使用して、使用する前に新しいアップデーターを作成してから、更新が必要なクラスと属性、属性名にパラメーター渡す必要があります同時に、変更する属性はpublicvolatileキーワードで変更する必要があります

(5)高性能アトムクラス(アトミックアキュムレータ)

:次のように原子アキュムレータの4つのタイプがあります
DoubleAccumulator
DoubleAdder
LongAccumulator
LongAdderを

LongAdderを例にとると、導入の目的は、同時実行性の高い環境でのAtomicLongのスピンボトルネックの問題解決することです。
思想概述セグメンテーションの概念を使用し、値の値は配列に分散され、異なるスレッドは配列の異なるスロットにヒットします。各スレッドは、独自のスロットの値に対してのみCAS操作を実行し、最後に値を追加しますこれらのセグメントの最終的な値を取得します。

おすすめ

転載: blog.csdn.net/m0_46550452/article/details/107457918