0

常に「3」が出力されるためです。同期は不要ですか?実際のマルチスレッドの問題で問題が発生しているため、この単純なことをテストしています。これは、問題が大きいため、問題を説明するのに適していません。これは、状況を示すための簡略化されたバージョンです。

class Test {

public static int count = 0;

class CountThread extends Thread {

    public void run()
    {
        count++;
    }
}  

public void add(){
    CountThread a = new CountThread();
    CountThread b = new CountThread();
    CountThread c = new CountThread();

    a.start();
    b.start();
    c.start();

    try {
        a.join();
        b.join();
        c.join();
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }

}
public static void main(String[] args) {

    Test test = new Test();
    System.out.println("START = " + Test.count);

    test.add();

    System.out.println("END: Account balance = " + Test.count);
}
4

6 に答える 6

1

このコードはスレッドセーフではありません:

public static int count = 0;

class CountThread extends Thread {

    public void run()
    {
        count++;
    }
}

このコードは、1 つのシステムで何百万回も実行でき、毎回成功する可能性があります。これは、スレッドセーフであることを意味するものではありません。

の値がcount複数のプロセッサ キャッシュにコピーされるシステムを考えてみましょう。いずれかのキャッシュが強制的にメイン RAM にコピーされる前に、それらはすべて個別に更新される可能性があります。++それはアトミック操作ではないと考えてください。の読み取りと書き込みの順序によって、countデータが失われる可能性があります。

このコードを実装する正しい方法 (Java 5 以降を使用):

public static java.util.concurrent.atomic.AtomicInteger count =
                                 new java.util.concurrent.atomic.AtomicInteger();

class CountThread extends Thread {

    public void run()
    {
        count.incrementAndGet();
    }
}
于 2013-04-13T18:44:04.160 に答える
0

クラスをスレッドセーフにするには、 countを作成してvolatileスレッド間のメモリ フェンスを強制するか、 AtomicIntegerを使用するか、次のように書き換えます (私の好み):

class CountThread extends Thread {

    private static final Object lock = new Object();

    public void run()
    {
        synchronized(lock) {
            count++;
        }
    }
}  
于 2013-05-15T13:33:12.143 に答える