3

簡単なコード スニペットがあり、少し試してみましたが、次のコードでは、出力データの順序がわかりません。

public class Main {

    static int n = 100;

    public static synchronized int decreaseValue(){
        return --n;
    }

    public static void main(String[] args) throws InterruptedException, IOException {


        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        System.out.println("Thread1: "+ decreaseValue());
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"Thread1");
        t1.start(); 

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        System.out.println("Thread2: "+ decreaseValue());
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"Thread2");
        t2.start();


        while(true){
            try {
                System.out.println("Main Thread: "+ decreaseValue());
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

次の順序でそのような値を取得する理由を理解できません:

スレッド 1: 89 スレッド 2: 90 メインスレッド: 88

呼び出しスレッドの順序ではなく、N の値に注意してください。

Thread1: 99
Thread2: 98
Main Thread: 97
Main Thread: 95
Thread2: 94
Thread1: 96
Main Thread: 92
4

3 に答える 3

3

synchronized適切な順序を確保するために使用する必要がある場所、または同様のものを読んだに違いありません。「順序付け」という言葉は、あなたが念頭に置いている概念とは異なる概念に関係しています。つまり、同期ブロックの実行には常に何らかの明確な順序付けが存在するということです。注文は事前にわかりませんが、毎回あります。同期がなければ、その保証さえ得られません。あるスレッドが 1 つの順序を認識し、別のスレッドが別の順序を認識したり、他のスレッドによるアクションをまったく認識しない可能性があります。

あなたの編集について:

順不同で出力されることが懸念される場合、これはprintlnステートメントが の外部にsynchronizedあり、呼び出しとは無関係にインターリーブできるためdecreaseValueです。

于 2012-10-28T12:47:41.163 に答える
2

スレッドは並行して実行されます。それらの実行順序を予測することはできません。実行順序を優先するスレッド優先度を設定できます。

于 2012-10-28T12:41:49.853 に答える
1

スレッドは同時に実行されており、関数を呼び出す順序を強制するものは何もありませんdecreaseValue()。同じ量のスリープを行っているため、それらが順番に並んでいると予想されます:)が、スレッドがスリープから開始/再開するとすぐに、CPUはスレッドを実行中のキューに配置します(実行順序を作成し、これは、同期が保証する順序です)。このため、印刷の順序は、CPU が実行中のキューにスレッドを配置する方法に依存します。

印刷順序に疑問がある場合は、コンソールの印刷も同期されます (ただし、recreaseValue と同じブロック内ではありません)。値を減らすのと同じロジックが印刷に適用されます。

値が減少したのと同じ順序で印刷を表示したい場合は、decreaseValue()関数内で印刷を移動できます。ただし、これは値が減らされる順序には影響しません。

于 2012-10-28T12:37:19.937 に答える