3

x++このコードを学生から入手しましたが、とが関与する競合状態のため、正しく動作しませんx--。彼はこのバグを取り除こうとしてメソッドに追加synchronizedしましたが、明らかに、これはスレッドが同じオブジェクトに入るのを排除するだけで (これはそもそも問題ではありませんでした)、独立したオブジェクトが同じ静的変数を更新するのを妨げません。同時に。run()run()x

public class DataRace implements Runnable {
  static volatile int x;

  public synchronized void run() {
    for (int i = 0; i < 10000; i++) {
          x++;
          x--;
    }
  }

  public static void main(String[] args) throws Exception {
    Thread [] threads = new Thread[100];

    for (int i = 0; i < threads.length; i++)
        threads[i] = new Thread(new DataRace());
    for (int i = 0; i < threads.length; i++)
        threads[i].start();
    for (int i = 0; i < threads.length; i++)
        threads[i].join();

    System.out.println(x); // x not always 0!
  }
}

で同期できないxため (原始的であるため)、私が考えることができる最善の解決策は、 のような新しい静的オブジェクトを作成し、ブロック内にandstatic String lock = "";を囲み、をロックすることです。しかし、これは非常に厄介なようです。より良い方法はありますか?x++x--synchronizedlock

4

3 に答える 3

6

を使用すると、必要な処理が実行され、操作をアトミックAtomicIntegerにする意図が明確になります。x次のかなりの数の実行の後、私は0毎回'sを取得しました:

import java.util.concurrent.atomic.AtomicInteger;

public class DataRace implements Runnable {
    static volatile AtomicInteger x = new AtomicInteger(0);

    public void run() {
        for (int i = 0; i < 10000; i++) {
            x.incrementAndGet();
            x.decrementAndGet();
        }
    }

    public static void main(String[] args) throws Exception {
        Thread[] threads = new Thread[100];

        for (int i = 0; i < threads.length; i++)
            threads[i] = new Thread(new DataRace());
        for (int i = 0; i < threads.length; i++)
            threads[i].start();
        for (int i = 0; i < threads.length; i++)
            threads[i].join();

        System.out.println(x); // x **is now** always 0!
    }
}
于 2012-12-13T01:24:01.283 に答える
1

変数xは静的でクラスに存在するため、変数へのアクセスはそのクラスで同期する必要があります。静的メソッドを作成するか、同期ブロックを使用しDataRace.classます。

于 2012-12-14T11:02:24.120 に答える
1

AtomicIntegerはあなたが探しているものです。

于 2012-12-13T01:22:25.293 に答える