2015-08-31 41 views
-2

好吧人們..我又回來了(最近似乎是我的家)。Java:超過10,000次迭代的線程連接不一致

我正在瀏覽多線程編程YouTube vids的整個洞穴。這個特定的使用2個線程,通過一個for循環,每個變量加1個變量10,000次。所以你加入他們,所以結果是20,000完成。

public class main { 

private int count = 0; 

public static void main(String[] args) { 
    main main = new main(); 
    main.doWork(); 
} 

public void doWork(){ 

    Thread t1 = new Thread(new Runnable(){ 
     public void run(){ 

      for (int i = 0; i < 10000; i++){ 
       count++; 
      } 
     } 
    }); 

    Thread t2 = new Thread(new Runnable(){ 
     public void run(){ 

      for (int i = 0; i < 10000; i++){ 
       count++; 
      } 
     } 
    }); 

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

    try { 
     t1.join(); 
     t2.join(); 
    } catch (InterruptedException ex) { 
     Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex); 
    } 


    System.out.println("Count is: " + count); 
    } 
} 

事情是..當我改變迭代:

我< 10 = 20(正確的)

我< 100 = 200(正確)

我< 1000 = 2000 (正確)

i < 10000 = 13034(首次運行)

= 14516(第二輪)

= ...等等。

爲什麼不是妥善處理數以萬計的迭代?

+2

答案很明顯:您有共享的不可同步的可變數據。 – duffymo

+0

哦,我的天啊......我需要去睡覺......那是一個可怕的問題 – Podis

回答

1

您已經演示了經典的競爭條件,當2個或更多線程以相互衝突的方式讀取和寫入同一變量時,會發生這種情況。出現這種情況是因爲操作者++不是一個原子操作 - 多個操作正在發生,和一個線程可能操作之間被中斷在,例如:

  1. 螺紋t1讀取count0),計算增加的​​值(1),但它尚未將該值存回count
  2. 主題t2讀取count(仍然0),並計算增加的​​值(1),但它並沒有存儲值回count呢。
  3. 主題t1將其1的值存回count
  4. 螺紋t2將其1值存回count

發生了兩次更新,但最終結果只是增加了1。不得中斷的一組操作是臨界區

這似乎發生了20,000 - 13,034次,即第一次執行時的6,966次。你可能已經得到了下限的幸運,但無論邊界的大小如何,競爭條件都可能發生。

在Java中,有幾種解決方案:

  1. synchronized blocks周圍的臨界區(既count++線),鎖定在this
  2. count更改爲AtomicInteger,它自己封裝了這些操作。 getAndIncrement方法將取代這裏的++運營商。
+0

這是一個很好的解釋! – Podis

相關問題