2014-12-20 75 views
0

我不明白爲什麼計數器的輸出每次都是不同的隨機數。當我在run()方法中打印出計數器時,它每次都是100000,但是當我評論該語句時,它會給出一個隨機數。在run()方法中,爲什麼counter是一個隨機數?

public class Answer extends Thread { 
     private static int counter = 0; 
     private static final int THREADS = 4; 
     public static final int COUNT = 100000; 
     public static void main(String[] args) { 
     Answer[] threads = new Answer[THREADS]; 
     for (int i = 0; i < THREADS; i++) { 
      threads[i] = new Answer(); 
      threads[i].start(); 
     } 
     try { 
      for (int i = 0; i < THREADS; i++) { 
       threads[i].join(); 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
} 
     System.out.println("Counter: " + counter); 
     } 
     public void run() { 
     for (int i = 0; i < COUNT/THREADS; i++) { 
      counter++; 
      //System.out.println(counter); 
     } 
} } 
+0

爲什麼你認爲讓「反」成爲靜態會是一個好主意?你是否經常宣佈變量是靜態的?你爲什麼要那麼做? –

回答

0

您的計數器變量是靜態的,並在您創建的所有線程之間共享,並且每個線程獨自更改計數器。嘗試從計數器變量中去除「靜態」。

此:

private static int counter = 0; 

向該:

private int counter = 0; 
0

counter是不通過任何鎖定或同步保護的線程之間的共享變量,所以對各個線程的counter++語句將「以不可預知的方式踐踏對方「。據推測,println引入了足夠的延遲來抵消這一點,儘管這無法保證100%。你在做什麼完成...?!

1

操作

counter++ 
在你的線程代碼

是不是線程安全的。你的線程正在逐步實施彼此的操作。

通過純粹的運氣,println的線程安全部分正在同步您線程的操作,以防止靜態變量的不良交互。當您註銷println電話時,您會失去該幸運同步。

如果您需要爲生產使用類似的東西,您可以使用同步變量。

1

這些是以下兩個原因。

  • 計數器++
  • 線程調度。

計數器++

它不是線程安全的。

Ex。 計數器= 0. 線程1 &線程2嘗試同時增加該值。兩者都會從主內存中獲取價值。線程內存遞增。所以現在計數器是1.在主內存中更新爲1而不是2. 您可以使用volatileAtomicInteger來克服此問題。

線程調度:

線程調度是由OS完成。無法保證順序。即使您以相同的順序提交thread1 & thread2 & thread3。它可能按不同的順序運行。

相關問題