1

マルチスレッドの同期インクリメント関数を作成しましたが、一貫した出力が表示されません:-

$ java Main
count: 999883

$ java Main
count: 1000000

$ java Main
count: 999826

$ java Main
count: 1000000

$ java Main
count: 1000000

私は同期されたカウンターを持っています:-

public class Counter {
    public int count;
    synchronized void inc() {
        count = count+1;
    }
    int getCount() {
        return count;
    }
}

カウンター オブジェクトで初期化され、それを 1000 回インクリメントするスレッド クラス:-

public class CountPrimesRunnable implements Runnable {
    private Counter c;

    public CountPrimesRunnable(Counter c) {
        this.c = c;
    }

    public void run() {
        for (int i = 0; i < 1000; i++)
            c.inc();
    }
}

そして、一度に 1000 個のスレッドを作成する Main クラス:-

public class Main {
    public static void main(String[] args) {
        int numberOfThreads = 1000;
        Thread[] worker = new Thread[numberOfThreads];
        Counter c = new Counter();
        for (int i = 0; i < numberOfThreads; i++)
            worker[i] = new Thread(new CountPrimesRunnable(c));

        for (int i = 0; i < numberOfThreads; i++)
            worker[i].start();

        System.out.println("count: " + c.count);
    }
}

私が見逃しているのは何ですか?

4

2 に答える 2

4

しかし、一貫した出力が表示されません:-

これは、コードからmainは、他のすべてのスレッドがジョブを完了した後にスレッドが常に終了するかどうかわからないためです。結果が 未満になる場合があります1000000。これは、メイン スレッドが終了した後も一部のスレッドが実行される場合です。

Thread#join() 新しく作成された各スレッドでメソッドを呼び出してmain、for ループの後に実行を続行する前に、メソッドがそれらのスレッドがすべて終了するのを待機するようにすることができます。

joinそのため、開始された各スレッドで呼び出す別の for ループを追加する必要があります。また、最初の for ループとマージすることで、2 番目の for ループの使用を避けることができます。

for (int i = 0; i < numberOfThreads; i++) {
    worker[i] = new Thread(new CountPrimesRunnable(c));
    worker[i].start();
}

for (int i = 0; i < numberOfThreads; i++) {
    worker[i].join();
}

joinaThread A内からaを呼び出すとThread B、は停止したThread B後にのみさらに実行を続けThread Aます。

于 2013-02-17T06:00:49.607 に答える
1
public class Counter {
    public int count;
    synchronized void inc() {
        count = count+1;
    }

    //this method must also be synchronized for establishing the happens-before relationship
    synchronized int getCount() {
        return count;
    }
}

get と set の両方が同じ lockで同期されている場合にのみ、最新の値が表示されることが保証されます。

また、join を呼び出して、すべてのスレッドが実行を完了するのを待つ必要があります。

于 2013-02-17T06:11:26.470 に答える