-1

次のようなコードがあります。

public class Count extends Thread {
    static IntCell n = new IntCell();

    public void run() {
        int temp;
        for (int i = 0; i < 200000; i++) {
            temp = n.getN();
            n.setN(temp + 1);
        }
    }

    public static void main(String[] args) {
        Count p = new Count();
        p.setName("Watek1");
        Count q = new Count();

        p.start();
        q.start();

        try {
            p.join();
            q.join();  
        }
        catch (InterruptedException e) {
            System.out.println(e);
        }

        System.out.println("The value of n is " + n.getN());
    }
}

class IntCell {
    private int n = 0;
    public int getN() {
        return n;
    }
    public void setN(int n) {
        this.n = n;
    }
}

2 つのスレッドがあり、n の値に 1 を追加します (静的クラス内)。このコードを実行すると、n 値の値が 400000 に等しくなることはありませんが、それについての何かです。なぜこのようなことが起こっているのですか?

4

3 に答える 3

3

これは、マルチスレッドの基本的な問題の 1 つです。値を取得し、インクリメントして格納することは、「アトミック」と呼ばれるものではありません。つまり、これを行うには複数の操作が必要です。ここで何が起こるか: 1 つのスレッドが値 X で N を取得し、もう 1 つのスレッドも同様に取得します。両方のスレッドがインクリメントし、X+1 を新しい N として格納します。どちらもローカル カウントを 1 増やしましたが、N も 1 だけインクリメントされました。

これが発生するかどうか、および N が期待値からどれだけ逸脱するかは、議論のためにランダムです。

AtomicInteger などのクラスを確認し、mutex と呼ばれるものについて調べてください。

于 2013-01-01T23:52:51.267 に答える
1

競合状態が発生しています。同期ステートメント(下記)を参照してください...

public void run() {
    int temp;
    for (int i = 0; i < 200000; i++) {
        synchronized(n) {
          temp = n.getN();
          n.setN(temp + 1);
        }
    }
}
于 2013-01-02T00:00:01.170 に答える
0

あなたの質問に対する簡単な答えは、両方のスレッドによって実行されるn.getN()n.setN(temp + 1)の呼び出しが互いにインターリーブするためです。次に例を示します。

Thread 1: n.getN() // returns 100
Thread 2: n.getN() // also returns 100
Thread 1: n.setN(temp + 1) // sets 101
Thread 2: n.setN(temp + 1) // also sets 101

意図した結果を得るには、スレッド同期またはその他の方法を実装する必要があります。

Java SEチュートリアルの同時実行の章に時間を費やすことをお勧めします: http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html

于 2013-01-02T00:28:52.840 に答える