2012-04-25 69 views
3

以下代碼應該通過使用common方法來防止數據競速。但由於某種原因,輸出始終爲19915-19980。如果不是數據競賽,它不應該是20000嗎?學習使用阻止數據競爭條件的線程

public class SyncVarDataRace extends Thread { 

    private static int common = 0; 

    public void run(){ 
     synchronized((Integer)common){ 
      int local = common; 
      local+=1; 
      common = local; 
     } 
    } 


    public static void main(String[] args) throws InterruptedException { 
     SyncVarDataRace[] allThreads = new SyncVarDataRace[20000]; 

     for(int i = 0; i < allThreads.length; i++){ 
      allThreads[i] = new SyncVarDataRace(); 
     } 

     for(SyncVarDataRace d: allThreads){ 
      d.start(); 
     } 

     for(SyncVarDataRace d: allThreads){ 
      d.join(); 
     } 

     System.out.println(common); 
    } 
} 

回答

5

您正嘗試在每次都是不同對象的自動裝箱對象上進行同步。

synchronized((Integer)common){ 

整點就是在每個線程中的同一個對象上進行同步。即使你讓common成爲Integer,只要你將它分配給另一個值,它將是一個不同的對象。

您需要鎖定一個常量對象。我會建議在定義了本地對象,您可以同步上:

private final static Object lock = new Object(); 
private static int common = 0; 
... 

synchronized (lock) { 
    common++; 
} 

這可能是在這種特殊情況下更好的,你可以考慮使用一個AtomicInteger。這可以讓你在不進行任何同步的情況下執行下面的操作

private static AtomicInteger common = new AtomicInteger(0); 
... 

// no need to synchronize since that is handled by the class 
common.incrementAndGet();