CASとは何ですか?Java で CAS を使用する方法

CAS は Compare And Swap の略で、同じ共有リソースを変更するときに複数のスレッドが競合状態に遭遇しないようにするために使用されるノンブロッキング同時実行制御テクノロジであり、それによって従来のロック メカニズムのさまざまな問題を回避します。問題。Java では、CAS は主に java.util.concurrent.atomic パッケージの下のいくつかのクラスとメソッドを通じて実装されます。Java での CAS とその使用について詳しく見てみましょう。

ここに画像の説明を挿入します

CASとは何ですか?

CAS はノンブロッキング同時実行制御テクノロジであり、主に、複数のスレッドが同じ共有リソースに同時にアクセスするときに発生する可能性のある競合状態の問題を解決するために使用されます。データの一貫性と正確性を確保するには、通常、共有リソースをロックする同期メカニズムを採用する必要があります。ただし、従来のロック メカニズムでは、同時実行性が高いシナリオでは深刻なパフォーマンス上の問題が発生します。これは、すべてのスレッドが動作前にロックが解放されるのを待つ必要があるためです。これにより、多数のスレッドがブロックされ、ウェイクアップされ、その結果、パフォーマンスが低下します。システムの同時実行パフォーマンス。

この問題を解決するために、CAS が登場しました。ロックを使用せずにデータの同期と同時実行制御を実現できるロックフリー同期機構です。CAS の基本的な考え方は、操作を実行する前に、まず現在のメモリ内の値が期待値と等しいかどうかを比較し、等しい場合は変更操作を実行し、等しくない場合は変更操作を実行するというものです。メモリ内の値が期待値と等しくなるまで比較は実行されず、期待値が等しくなるまで継続されます。このプロセス中にスレッドのブロックやウェイクアップが発生しないため、システムの同時実行パフォーマンスが向上します。

Java の CAS

Java では、CAS は主に java.util.concurrent.atomic パッケージ内のいくつかのクラスとメソッドを通じて実装されます。これらのクラスとメソッドは、複数のスレッドが同じ共有リソースに同時にアクセスするときに競合状態が発生しないようにアトミック操作を実行する方法を提供します。

アトミックブール値

AtomicBoolean クラスは、ブール型のアトミック変数を表し、変数の操作がアトミックであることを保証できる、compareAndSet、getAndSet、weakCompareAndSet などのいくつかのアトミック操作メソッドを提供します。

サンプルコードは次のとおりです。

import java.util.concurrent.atomic.AtomicBoolean;

public class AtomicBooleanTest {
    
    
    private static AtomicBoolean flag = new AtomicBoolean(false);

    public static void main(String[] args) throws InterruptedException {
    
    
        Thread t1 = new Thread(() -> {
    
    
            while (!flag.compareAndSet(false, true)) {
    
    
                System.out.println(Thread.currentThread().getName() + ": try again");
            }
            System.out.println(Thread.currentThread().getName() + ": success");
        },"Thread-1");

        Thread t2 = new Thread(() -> {
    
    
            while (!flag.compareAndSet(false, true)) {
    
    
                System.out.println(Thread.currentThread().getName() + ": try again");
            }
            System.out.println(Thread.currentThread().getName() + ": success");
        },"Thread-2");

        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

この例では、AtomicBoolean 型の変数 flag を作成し、成功するまで継続的に flag の値を false から true に変更しようとする 2 つのスレッド t1 と t2 を定義します。2 つのスレッドが同時にフラグ値を変更しようとした場合、1 つのスレッドのみが成功し、もう 1 つのスレッドは成功するまで試行を続けます。

アトミック整数

AtomicInteger クラスは整数のアトミック変数を表し、変数の操作がアトミックであることを保証できる、compareAndSet、getAndSet、incrementAndGet などのいくつかのアトミック操作メソッドを提供します。

サンプルコードは次のとおりです。

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerTest {
    
    
    private static AtomicInteger count = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
    
    
        Thread t1 = new Thread(() -> {
    
    
            for (int i = 0;i < 10000; i++) {
    
    
                count.incrementAndGet();
            }
        },"Thread-1");

        Thread t2 = new Thread(() -> {
    
    
            for (int i = 0; i < 10000; i++) {
    
    
                count.incrementAndGet();
            }
        },"Thread-2");

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("count = " + count.get());
    }
}

この例では、AtomicInteger 型の変数 count を作成し、2 つのスレッド t1 と t2 を定義します。どちらも count を 1 万回インクリメントします。AtomicInteger が提供する incrementAndGet メソッドはアトミックであるため、複数のスレッドが同時に count をインクリメントしても競合状態は発生せず、count の最終値は正確になります。

アトミックリファレンス

AtomicReference クラスは、参照型のアトミック変数を表し、変数の操作がアトミックであることを保証できる、compareAndSet、getAndSet、weakCompareAndSet などのいくつかのアトミック操作メソッドを提供します。

サンプルコードは次のとおりです。

import java.util.concurrent.atomic.AtomicReference;

public class AtomicReferenceTest {
    
    
    private static class Student{
    
    
        private String name;
        private int age;

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

        public String getName() {
    
    
            return name;
        }

        public int getAge() {
    
    
            return age;
        }

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

        public void setAge(int age) {
    
    
            this.age = age;
        }

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

    private static AtomicReference<Student> student = new AtomicReference<>(new Student("张三", 18));

    public static void main(String[] args) {
    
    
        Student newStudent = new Student("李四", 20);
        student.compareAndSet(student.get(), newStudent);
        System.out.println(student.get());
    }
}

この例では、AtomicReference 型の変数 Student を作成し、Student 型のオブジェクト newStudent を定義します。CompareAndSet メソッドを使用して、アトミック変数 Student の値を元の Student オブジェクトから newStudent オブジェクトに変更します。AtomicReference によって提供される CompareAndSet メソッドはアトミックであるため、複数のスレッドが同時に Student を変更しても競合状態は発生しません。 。

要約する

CAS は、ロックを使用せずにデータ同期と同時実行制御を実現できるノンブロッキング同時実行制御テクノロジであり、これによりシステムの同時実行パフォーマンスが向上します。Java では、CAS は主に java.util.concurrent.atomic パッケージの下のいくつかのクラスとメソッドを通じて実装されており、複数のスレッドが同じ共有リソースに同時にアクセスできるようにするアトミック操作の方法を提供します。 。実際の開発において、共有リソースの同時実行制御が必要な場合は、CAS テクノロジーの使用を優先することをお勧めします。

おすすめ

転載: blog.csdn.net/JasonXu94/article/details/131937888