Java 中的 AtomicInteger

今天我們將研究 Java 中的 AtomicInteger原子操作 是在單個任務單元中執行的,不會受到其他操作的干擾。 在多線程環境中,原子操作是必要的,以避免數據不一致性。

AtomicInteger

讓我們創建一個簡單的多線程程序,其中每個線程將共享的 count 變量增加 4 次。 因此,如果有兩個線程,則在它們完成後,count 的值應該為 8。 JavaAtomic.java

package com.journaldev.concurrency;

public class JavaAtomic {

    public static void main(String[] args) throws InterruptedException {

        ProcessingThread pt = new ProcessingThread();
        Thread t1 = new Thread(pt, "t1");
        t1.start();
        Thread t2 = new Thread(pt, "t2");
        t2.start();
        t1.join();
        t2.join();
        System.out.println("Processing count=" + pt.getCount());
    }

}

class ProcessingThread implements Runnable {
    private int count;

    @Override
    public void run() {
        for (int i = 1; i < 5; i++) {
            processSomething(i);
            count++;
        }
    }

    public int getCount() {
        return this.count;
    }

    private void processSomething(int i) {
        // 處理某些工作
        try {
            Thread.sleep(i * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

如果您運行上面的程序,您將注意到 count 的值在 5、6、7、8 之間變化。 原因是因為 count++ 不是原子操作。 因此,當一個線程讀取它的值並將其增加一時,其他線程已經讀取了舊值,導致了錯誤的結果。 要解決這個問題,我們必須確保對 count 的增量操作是原子的,我們可以使用 同步 來做到這一點,但是 Java 5 java.util.concurrent.atomic 提供了 int 和 long 的包裹類,可以用來實現這種原子操作,而無需使用同步。

Java AtomicInteger 範例

這是更新後的程式,它將始終將計數值輸出為8,因為 AtomicInteger 方法 incrementAndGet() 會原子性地將當前值增加一。

package com.journaldev.concurrency;

import java.util.concurrent.atomic.AtomicInteger;

public class JavaAtomic {

    public static void main(String[] args) throws InterruptedException {

        ProcessingThread pt = new ProcessingThread();
        Thread t1 = new Thread(pt, "t1");
        t1.start();
        Thread t2 = new Thread(pt, "t2");
        t2.start();
        t1.join();
        t2.join();
        System.out.println("Processing count=" + pt.getCount());
    }
}

class ProcessingThread implements Runnable {
    private AtomicInteger count = new AtomicInteger();

    @Override
    public void run() {
        for (int i = 1; i < 5; i++) {
            processSomething(i);
            count.incrementAndGet();
        }
    }

    public int getCount() {
        return this.count.get();
    }

    private void processSomething(int i) {
        // 處理某些工作
        try {
            Thread.sleep(i * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

使用 Concurrency 類進行原子操作的好處是我們不需要擔心同步。這提高了代碼的可讀性,並且減少了錯誤的機會。同時,原子操作的並發類被認為比涉及鎖定資源的同步更有效率。

Source:
https://www.digitalocean.com/community/tutorials/atomicinteger-java