3

次のコードは、共通の同期メソッドを使用してデータ競合を防止することになっています。しかし、何らかの理由で、出力は常に 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);
    }
}
4

1 に答える 1

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();
于 2012-04-25T03:40:10.563 に答える