簡體   English   中英

數據在AtomicReference的各個元素上進行競爭

[英]Data Races on individual elements of an AtomicReference

我有一個與通過原子參考訪問單個元素有關的問題。 如果我有一個IntegerArray和一個原子引用;是否會通過AtomicReference變量讀取和寫入數組的各個元素導致數據競爭?

在下面的代碼中:num是一個整數數組,其中aRnumbers是數組的原子引用。 在線程1和2中; 我訪問aRnumbers.get()[1]並將其遞增1。

我可以通過原子引用訪問單個元素而無需數據競爭,每次使用22作為兩個線程完成后主線程中aRnumbers.get()[1]的輸出。

但是,因為原子引用是在數組上定義的,而不是在單個元素上定義的; 在這種情況下不應該有數據競爭導致21/22作為輸出?

在這種情況下,沒有數據競爭是擁有AtomicIntegerArray數據結構的動機,該結構為每個元素提供單獨的AtomicReference嗎?

請在下面找到我想要運行的java代碼。有人可以告訴我哪里出錯了。

import java.util.concurrent.atomic.AtomicReference;

public class AtomicReferenceExample {


    private static int[] num= new int[2];
    private static AtomicReference<int[]> aRnumbers;

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new MyRun1());
        Thread t2 = new Thread(new MyRun2());

        num[0]=10;
        num[1]=20;

        aRnumbers = new AtomicReference<int[]>(num);

        System.out.println("In Main before:"+aRnumbers.get()[0]+aRnumbers.get()[1]);

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

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

        System.out.println("In Main after:"+aRnumbers.get()[0]+aRnumbers.get()[1]);
    }

    static class MyRun1 implements Runnable {
        public void run() {
            System.out.println("In T1 before:"+aRnumbers.get()[1]);
            aRnumbers.get()[1]=aRnumbers.get()[1]+1;

        }
    }

    static class MyRun2 implements Runnable {
        public void run() {
            System.out.println("In T2 before:"+aRnumbers.get()[1]);
            aRnumbers.get()[1]=aRnumbers.get()[1]+1;

        }

    }

}

在這種情況下不應該有數據競爭導致21/22作為輸出?

的確有。 你的線程很短暫,很可能它們不會同時運行。

在這種情況下,沒有數據競爭是擁有AtomicIntegerArray數據結構的動機,該結構為每個元素提供單獨的AtomicReference嗎?

是的。

誰能讓我知道我哪里出錯了。

啟動一個線程需要1 - 10毫秒。

即使沒有代碼被JIT,增加這樣的值也可能需要<< 50微秒。 如果它被優化,每增量需要大約50-200納秒。

由於起步比起操作時間大約20 - 200倍,因此它們不會同時運行,因此沒有競爭條件。

嘗試將值遞增幾百萬次,因此您有一個競爭條件,因為兩個線程同時運行。

增加元素包括三個步驟:

  1. 讀取價值。
  2. 增加價值。
  3. 寫回價值。

可能發生競爭條件。 舉一個例子:線程1讀取值(假設為20)。 任務切換。 線程2讀取值(再次為20),將其遞增並將其寫回(21)。 任務切換。 第一個線程遞增該值並將其寫回(21)。 因此,當進行2次遞增操作時,最終值仍然僅增加1。

在這種情況下,數據結構沒有幫助。 線程安全集合有助於在並發線程添加,訪問和刪除元素時保持結構一致。 但是在這里,您需要在增量操作的三個步驟中鎖定對元素的訪問。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM