0

java.util.concurrent パッケージの API ドキュメントを読みましたが、明らかに誤解しているものがあります。概要は言う

単一変数でのロックフリー スレッドセーフ プログラミングをサポートするクラスの小さなツールキット。

ただし、小さなテスト アプリケーションでは、少なくともスレッド間で共有されている場合、AtomicInteger クラスがスレッド セーフを提供しないことが示されています ( getAndSet / increment メソッド自体が少なくともアトミックであることは認めます) 。

テスト:

import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntTest
{
    public static void main(String[] args) throws InterruptedException
    {
        AtomicInteger atomicInt = new AtomicInteger(0);
        WorkerThread w1 = new WorkerThread(atomicInt);
        WorkerThread w2 = new WorkerThread(atomicInt);
        w1.start();
        w2.start();
        w2.join(); // <-- As pointed out by StuartLC and BarrySW19, this should be w1.join(). This typo allows the program to produce variable results because it does not correctly wait for *both* threads to finish before outputting a result.
        w2.join();
        System.out.println("Final value: " + atomicInt.get());
    }

    public static class WorkerThread extends Thread
    {
        private AtomicInteger atomicInt = null;
        private Random random = new Random();

        public WorkerThread(AtomicInteger atomicInt)
        {
            this.atomicInt = atomicInt;
        }

        @Override
        public void run()
        {
            for (int i = 0; i < 500; i++)
            {
                this.atomicInt.incrementAndGet();
                try
                {
                    Thread.sleep(this.random.nextInt(50));
                }
                catch(InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
}

このクラスを実行すると、常に 950 から 1000 の範囲の結果が得られますが、常に正確に 1000 が表示されると予想されます。

2 つのスレッドがこの共有 AtomicInteger 変数にアクセスすると、一貫した結果が得られない理由を説明できますか? スレッドセーフ保証を誤解していませんか?

4

1 に答える 1

1

単純なカット アンド ペースト エラーのように見えます。スレッド "w2" に 2 回参加しており、"w1" には参加していません。現時点では、'final' 値を出力すると、スレッド "w1" がまだ半分の時間実行されていると予想されます。

于 2015-03-20T12:18:49.203 に答える