2012-04-25 19 views
3

次のコードは、synchronizedメソッドを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){ 

全体的なポイントは、各スレッドの同じオブジェクトで同期することです。 commonIntegerにしても、別の値に割り当てるとすぐに別のオブジェクトになります。

代わりに定数オブジェクトをロックする必要があります。私はあなたが上で同期させることができ、ローカルオブジェクトを定義する推薦:

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(); 
関連する問題