次のようなJavaアトミッククラスアプリケーションシナリオ:AtomicIntegerの使用

 

Javaには、Atomicで始まるクラスがいくつかあります。この一連のクラスをアトミック操作クラスと呼びます。アトミッククラスはCASと揮発性に基づいて構築されています。CASは非ブロッキングアルゴリズムの一般的な実装であり、ブロッキングアルゴリズムである同期よりも優れたパフォーマンスを発揮します。

最も単純なクラスであるAtomicIntegerを例にとってみましょう。これはint変数と同等であり、Intのi ++を実行する場合、アトミック操作ではありません。AtomicIntegerのincrementAndGetを使用すると、アトミック操作が保証されます。具体的なクラスは次のとおりです。

さらに面倒なことはせずに、例を挙げて話しましょう。

質問:2つのスレッドがあり、それぞれがグローバル整数変数iを1ずつインクリメントします。各スレッドは5000回実行されます。従来のintの使用法によると、コードは次のとおりです。

 

private static int m = 0;

public static void main(String[] args) throws InterruptedException {
    CountDownLatch cdl = new CountDownLatch(2);

    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int j = 0; j < 5000; j++) {
                m++;
            }
            cdl.countDown();
        }
    });
    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int j = 0; j < 5000; j++) {
                m++;
            }
            cdl.countDown();
        }
    });
    t1.start();
    t2.start();

    cdl.await();
    System.out.println("result=" + m);
}

 

最後に、上記のコードを実行すると、結果は10000になる可能性がありますが、ほとんどの場合、10000ではなく、いくつかの乱数です。ここでの問題はm++です。m++に同期されたキーワードを追加すると、並行性の問題も解決できます。しかし、同期は重すぎます。したがって、アトミック操作クラスAtomicIntegerを使用して達成することを検討できます。具体的な実装コードは次のとおりです。

 

public static void main(String[] args) throws InterruptedException {
    CountDownLatch cdl = new CountDownLatch(2);
    AtomicInteger i = new AtomicInteger(0);

    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int j = 0; j < 5000; j++) {
                i.incrementAndGet();
            }
            cdl.countDown();
        }
    });
    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int j = 0; j < 5000; j++) {
                i.incrementAndGet();
            }
            cdl.countDown();
        }
    });
    t1.start();
    t2.start();

    cdl.await();
    System.out.println("result=" + i.get());
}

これで、何度実行しても、結果は常に10000になります。

説明:

  1. m ++は不可分操作ではありませんが、incrementAndGetは不可分操作メソッドです

おすすめ

転載: blog.csdn.net/qq_35222843/article/details/114314657