2012-12-05 128 views
4

帶同步的簡單多線程測試。我想如果它是「同步的」,其他線程會等待。我錯過了什麼?使用同步的Java多線程不是線程安全的

public class MultithreadingCounter implements Runnable { 

    static int count = 0; 

    public static void main(String[] args) { 
     int numThreads = 4; 
     Thread[] threads = new Thread[numThreads]; 

     for (int i = 0; i < numThreads; i++) 
      threads[i] = new Thread(new MultithreadingCounter(), i + ""); 

     for (int i = 0; i < numThreads; i++) 
      threads[i].start(); 

     for (int i = 0; i < numThreads; i++) 
      try { 
       threads[i].join(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
    }   

    @Override 
    public void run() { 
     increment(); 
    } 

    public synchronized void increment(){ 
      System.out.print(Thread.currentThread().getName() + ": " + count + "\t"); 
      count++; // if I put this first or increment it directly in the print line, it works fine. 
    } 
} 

我認爲這將顯示類似:

0: 1 2: 0 1: 2 3: 3  

但其實際輸出:

0: 0 2: 0 1: 0 3: 3  

和其他變化是這樣的。它應該顯示每個增量(即0,1,2,3)不按順序...

回答

7

您的​​關鍵字位於實例方法上。沒有兩個線程可以同時執行您的線程對象之一的此方法。但是,這不是你的代碼所做的。每個線程在自己的實例上執行該方法。同步不會做你想要的。如果它是一個static方法,它會。

+0

啊。我每天都會學到新的東西。謝謝。 – user1877411

+0

會使它成爲'static'(與'synchronized'結合)充分地關閉它,還是應該使變量volatile? –

+1

(正確)同步就足夠了。它已確保增量與後續讀取之間具有發生之前的關係,這是「易失性」會增加的所有內容。 –

1

increment方法應該是static

public static synchronized void increment() { 

現在,每個對象在個別情況下同步,但由於count是一個靜態變量,你應該Class對象本身上同步。

+1

我是讓你得到3000代表的人,耶:D – Doorknob

0

當在方法之前使用synchronized關鍵字時,它確保該方法只能針對該對象一次僅由一個線程執行。它不能確保其他對象的線程安全。