6

Javaスレッドでの安全でないデクリメント/インクリメントの結果について疑問に思っているので、私のプログラムがあります:

メインクラス:

public class Start {

    public static void main(String[] args) {

        int count = 10000000, pos = 0, neg = 0, zero = 0;

        for (int x=0; x<10000; x++) {

            Magic.counter = 0;

            Thread dec = new Thread(new Magic(false, count));
            Thread inc = new Thread(new Magic(true, count));

            dec.start();
            inc.start();

            try {
                inc.join();
                dec.join();
            } catch (InterruptedException e) {
                System.out.println("Error");
            }

            if (Magic.counter == 0)
                zero++;
            else if (Magic.counter > 0)
                pos++;
            else
                neg++;
        }

        System.out.println(Integer.toString(neg) + "\t\t\t" + Integer.toString(pos) + "\t\t\t" + Integer.toString(zero));
    }
}

スレッド クラス:

public class Magic implements Runnable {

    public static int counter = 0;

    private boolean inc;
    private int countTo;

    public Magic(boolean inc, int countTo) {
        this.inc = inc;
        this.countTo = countTo;
    }

    @Override
    public void run() {

        for (int i=0;i<this.countTo;i++) {

            if (this.inc)
                Magic.counter++;
            else
                Magic.counter--;
        }

    }
}

私はプログラムを数回実行しましたが、常に否定的な結果よりも肯定的な結果が得られます。また、スレッドの開始順序を変更しようとしましたが、何も変わりませんでした。いくつかの結果:

Number of results < 0 | Number of results > 0 | Number of results = 0

1103                8893                4
3159                6838                3
2639                7359                2
3240                6755                5
3264                6728                8
2883                7112                5
2973                7021                6
3123                6873                4
2882                7113                5
3098                6896                6
4

2 に答える 2

0

一般的に、これはJavaメモリモデルの動作方法によるものです。同期せずに2つの異なるスレッドで共有変数にアクセスしています。変数が揮発性であると宣言されておらず、アトマー操作を実行していません。調整および原子変数または揮発性変数がない場合、実行時にJVMによって実行されるスレッドコードの内部最適化につながります。また、メモリバリアを超えていない(つまり)不揮発性変数は、synchronizedスレッドごとにキャッシュされた値になります。したがって、キャッシュ内に2つの競合するスレッドローカルコピーが発生します。

Javaに逐次一貫性モデルがないこと、複雑なランタイム最適化、および使用されるJVMと基盤となるシステム(シングルコアまたはマルチコア、ハイパースレッディング)の特性を考えると、結果を決定論的に予測することは不可能です。 -Java言語モデルのスレッド規則。同じマシンでまったく同じコードを実行すると、同様の結果が得られる可能性がありますが、スレッドスケジューリング、他のOSプロセスのCPU使用率などの影響により、それらは完全に同じではない可能性があります。

JMMに関するいくつかのリソースは次のとおりです。http ://www.cs.umd.edu/~pugh/java/memoryModel/

于 2011-10-20T22:23:07.113 に答える