[英]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讀取值(假設為20)。 任務切換。 線程2讀取值(再次為20),將其遞增並將其寫回(21)。 任務切換。 第一個線程遞增該值並將其寫回(21)。 因此,當進行2次遞增操作時,最終值仍然僅增加1。
在這種情況下,數據結構沒有幫助。 線程安全集合有助於在並發線程添加,訪問和刪除元素時保持結構一致。 但是在這里,您需要在增量操作的三個步驟中鎖定對元素的訪問。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.