1

次のコードは、Windows 7 x86 jdk 7 (-ea をオン)で volatile の JLS の例に従って AssertionError をスローすべきではありませんか?

public class TestVolatile {
static volatile int i = 0;
static volatile int j = 0;

static void one() {
    i++;
    j++;
    assert (i>=j);
//:"one: i=" + i + " j=" + j;
}
static void two() {
    //System.out.println("i=" + i + " j=" + j);
    assert (i<=j);
    /*
    System.out.print("<i=" + i);
    for (int k = 0; k < 1000000; k++);
    System.out.println(", j=" + j+">");
    */
}
public static final int NUM_WORKERS =  4;

public static void main (String [] args) {
    final Worker [] workers = new Worker[NUM_WORKERS];
    final Thread [] workerThreads = new Thread[NUM_WORKERS];

    for (int i = 0; i < NUM_WORKERS; i++) {
        Worker w = new Worker(i);
        workers[i] = w;
        workerThreads[i] = new Thread(w,"workerThread_"+i);
    }

    for (int i = 0; i < NUM_WORKERS; i++) {
        workerThreads[i].start();
    }

}


}

final class Worker implements Runnable {
final int id;
volatile boolean notDone = true;


public Worker(int tid){
    id = tid;
}

@Override
public void run() {
    //System.out.println("worker start:" + id);
    try {
        while (notDone) {
            if (id  <  TestVolatile.NUM_WORKERS - 1) {
                TestVolatile.one();
            } else {
                TestVolatile.two();
            }
        }
    } catch (Exception e) {
        // TODO: handle exception
        e.printStackTrace();
    }
}
};
4

1 に答える 1

4

複数のスレッドが実行されていoneます。iおよびj揮発性であるため、変更は表示されますが、アトミック操作ではi++ありj++ません。また、ある段階でカウンターの 1 つが適切にインクリメントされない可能性が非常に高くなります。

たとえば、AssertionError をスローできる有効なスレッド インターリーブを示すために、i が 5 であるとします。

  • スレッド 1: i => 5 を読む
  • スレッド 2: i => 5 を読む
  • スレッド 1: temp = i + 1 => 6
  • スレッド 2: temp = i + 1 => 6
  • スレッド 1: i = temp => 6 と書く
  • スレッド 2: i = temp => 6 と書く
  • スレッド 1: j を読み取り、インクリメント => j = 6
  • スレッド 2: j を読み取り、インクリメント => j = 7

i と j は同期していないため、アサートインoneは失敗します。

しかし、データ競合が存在するにもかかわらず、プログラムの実行がアサーション エラーをスローしない可能性は依然としてあります。JLS は、プログラムが正常に実行されることを保証しませんが、実行されないとも言いません。

編集: JLS の「スレッドとロック」セクションを書いた人の 1 人が、実際に非常によく似た質問についてブログに投稿しています。コメントには、質問で参照している JLS セクションについても言及されています。JLS の例には書き込みスレッドが 1 つしかありません。

于 2013-01-13T19:46:54.290 に答える