1

私は5つの異なるスレッドを作成しようとしておりrun、静的変数のカウントを1ずつ増やすたびにメソッドに静的オブジェクトを出力しようとしています

プログラムのサンプル出力は次のとおりです。

pool-1-thread-1 Static Value before update 19
Thread going to sleep pool-1-thread-1
pool-1-thread-4 Static Value before update 19
Thread going to sleep pool-1-thread-4
pool-1-thread-3 Static Value before update 19
Thread going to sleep pool-1-thread-3
pool-1-thread-2 Static Value before update 19
Thread going to sleep pool-1-thread-2
pool-1-thread-5 Static Value before update 19
Thread going to sleep pool-1-thread-5
Thread coming out of sleep pool-1-thread-3  StaticTest.sInt 19
Thread coming out of sleep pool-1-thread-4  StaticTest.sInt 19
Thread coming out of sleep pool-1-thread-1  StaticTest.sInt 19
Thread coming out of sleep pool-1-thread-5  StaticTest.sInt 19
Thread coming out of sleep pool-1-thread-2  StaticTest.sInt 19

**pool-1-thread-5  OLD value 22 Static Value after update 23**
pool-1-thread-1  OLD value 21 Static Value after update 22
pool-1-thread-4  OLD value 20 Static Value after update 21
pool-1-thread-3  OLD value 19 Static Value after update 20
pool-1-thread-2  OLD value 23 Static Value after update 24

ここで私の質問は、スレッド 3 が最初にスリープ状態から抜け出したので、最初に印刷されたに違いありませんが、最初に印刷されたスレッド 5 であり、それも値 22 です。つまり、静的変数は、スレッド 5 がそれを取得する前に 3 回インクリメントされました、しかし、インクリメントされた値を私に出力しているときにランダムな順序が表示されるのはなぜですか。スリープから抜け出したのと同じ順序で印刷されているはずです。つまり、スレッド 3/4/1/5/2

考えを注いでください?スレッドがスリープ後に実行状態に戻った後のランダムな動作がなぜ欠けているのか

package com.test.concurrency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class StaticTest {

    public static Integer sInt = new Integer(19);

    public static void main(String[] args) {

        ExecutorService es = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            es.execute(new StaticTask());
        }

    }

}

class StaticTask implements Runnable {

    public void run() {

        String name = Thread.currentThread().getName();
        System.out.println(name + " Static Value before update "
                + StaticTest.sInt);
        try {
            System.out.println("Thread going to sleep " + name);
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Thread coming out of sleep " + name + "  StaticTest.sInt " + StaticTest.sInt);

        int local = StaticTest.sInt;
        StaticTest.sInt = new Integer(local + 1);

        System.out.println(name + "  OLD value " + local +" Static Value after update "
                + StaticTest.sInt);

    }
}
4

6 に答える 6

1

どちらが最初に実行されるかを制御または決定論的に知る方法はありません。最初にスレッドを開始したからといって、最初に実行されるとは限りません...

ループで 5 つのスレッドを実行していますが、最初のスレッドが最初に実行され、2 番目のスレッドが 2 番目に実行されるという保証はありません...

スレッドを特定の順序で実行したい場合は、何らかの結合または待機/通知ロジックを実行する必要があります。

于 2013-10-29T12:59:50.397 に答える
0

thread-3出力から、最初に目を覚ましたものであることは明らかです(はい、あなたは正しいです)、次に static int をインクリメントしました

pool-1-thread-5  OLD value 22 Static Value after update 23
pool-1-thread-1  OLD value 21 Static Value after update 22
pool-1-thread-4  OLD value 20 Static Value after update 21
pool-1-thread-3  OLD value 19 Static Value after update 20  --> static counter incr. from 19 to 20
pool-1-thread-2  OLD value 23 Static Value after update 24

上記の print ステートメントでは、出力している値から、最初に起動したスレッドが値をインクリメントして出力していることは明らかです。

予測できないのは、印刷シーケンスです。

低レベルで考えると、System.out.printステートメントはAsynchronousであるため、出力

于 2013-10-29T13:05:49.740 に答える
0

Java の並行性についてよく読んでください。スレッドが特定の順序で実行されることを期待しないでください。特に、共有リソースの周りでコードを同期する場合は除きます。ここから始めたいと思うかもしれません。

于 2013-10-29T13:01:27.763 に答える
0

ここで私の質問は、スレッド 3 が最初にスリープ状態から抜け出したため、最初に印刷されたに違いありませんが、最初に印刷されたスレッド 5 であり、値も 22 です。

5 つのスレッドが同時に実行されているため、指定された一連のステートメントが実行される順序は予測できません。スレッドが順序どおりに出てきたとしても3/4/1/5/2、残りのステートメントを実行している間、同じ順序が維持されるとは限りません。それがAsynchronous実行と呼ばれる理由です。

threads 3, 4, 1ステートメントを実行した可能性があります

int local =StaticTest.sInt;
StaticTest.sInt = new Integer(local + 1);

次々と(任意の順序で)thread 5、ステートメントを一度に実行する機会を得ました。

int local =StaticTest.sInt;
StaticTest.sInt = new Integer(local + 1);
System.out.println(name + "  OLD value " + local +" Static Value after update "
                + StaticTest.sInt);

これをコンソールに出力しました:

pool-1-thread-5  OLD value 22 Static Value after update 23

静的変数の値がによってStaticTest.sInt既に更新されている可能性があるためです。22threads 3, 4, 1

また、共有変数への同期アクセスを常に使用する必要があります。これにより、1 つのスレッドによって行われた変更が他のスレッドに表示され、同期アクセスを使用すると、共有変数に対する操作がアトミックになります。

public static synchronized Integer incrementSInt() {
    return StaticTest.sInt++;
}
于 2013-10-29T13:31:24.553 に答える