ホームページ  >  記事  >  Java  >  これは Java の面接で難しい質問だと聞きましたが?

これは Java の面接で難しい質問だと聞きましたが?

王林
王林転載
2021-01-11 09:54:052377ブラウズ

これは Java の面接で難しい質問だと聞きましたが?

まず質問の内容を見てみましょう:

(学習ビデオ共有: java ビデオ チュートリアル)

public class TestSync2 implements Runnable {
    int b = 100;          

    synchronized void m1() throws InterruptedException {
        b = 1000;
        Thread.sleep(500); //6
        System.out.println("b=" + b);
    }

    synchronized void m2() throws InterruptedException {
        Thread.sleep(250); //5
        b = 2000;
    }

    public static void main(String[] args) throws InterruptedException {
        TestSync2 tt = new TestSync2();
        Thread t = new Thread(tt);  //1
        t.start(); //2

        tt.m2(); //3
        System.out.println("main thread b=" + tt.b); //4
    }

    @Override
    public void run() {
        try {
            m1();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

このプログラムの出力?

プログラムの出力結果

main thread b=2000
b=1000
或
main thread b=1000
b=1000

ナレッジポイントの調査

インスタンスのロックを同期します。

同時実行時のメモリの可視性。

(より関連した面接の質問に関する推奨事項: Java の面接の質問と回答 )

Java では、マルチスレッド プログラムは理解とデバッグが最も難しく、多くの実行結果の倍 思ったよりもパフォーマンスが良くありませんでした。そのため、Java のマルチスレッドは特に難しく、私が大学で C 言語のレベル 2 を受験したとき、その問題は他の多くの優先順位と一致し、最終的な出力結果について尋ねられたことを漠然と覚えています。問題は、優先順位と統合の問題で、いくつかのランタイム オペレーターをテストしたかったのです。ただ暗記するだけですが、Java マルチスレッドについてはまだ十分に理解する必要があり、暗記してもうまくいきません。

簡単な分析から始めましょう:

この質問には 2 つのスレッド (メイン スレッド、サブスレッド) が含まれており、キーワードには synchronized と Thread.sleep が含まれます。
synchronized キーワードは依然として非常に複雑です (おそらく、正しく理解されていない場合があるため、上記の質問は少し誤解されるでしょう) その機能は、スレッド同期を実現することです (スレッド同期を実現するには多くの方法がありますが、単にこの方法については後続の記事で説明します)。はい、マスター Doug Lea の実装をいくつか検討する必要があります。その役割は、同期する必要があるコードをロックして、1 つのスレッドだけが同期ブロックに入ることができるようにすることです。スレッドがセキュリティのみを記憶するようにするための時間 (実際には悲観的な戦略)。

一般キーワード synchronized の使用法

ロック オブジェクトを指定: 指定されたオブジェクトをロックします。同期コードを入力する前に、指定されたオブジェクトのロックをアクティブにする必要があります。インスタンス メソッドに直接作用する: 現在のインスタンスをロックするのと同等 同期コードを入力する前に、現在のインスタンスのロックを取得する必要があります。静的メソッドに直接作用: 現在のクラスをロックするのと同等 同期コードを入力する前に、現在のクラスのロックを取得する必要があります。

上記のコード、同期された使用法は、実際には 2 番目の状況に属します。インスタンス メソッドに直接作用する: 現在のインスタンスをロックするのと同等 同期コードを入力する前に、現在のインスタンスのロックを取得する必要があります。

潜在的な誤解

同期についての理解が不十分なため、マルチスレッドが同期メソッドを実行することがよくあります。2 つのスレッドが 2 つの異なる同期メソッドを呼び出すとき、同期メソッドがあると考えるのは誤解です。メソッドを使用する場合は関係ありません。インスタンス メソッドに直接作用する: 現在のインスタンスをロックするのと同等 同期コードを入力する前に、現在のインスタンスのロックを取得する必要があります。同期メソッドを呼び出す場合。もう一方が通常のメソッドを呼び出しているかどうかは問題ではなく、両者の間には待機関係はありません。

これらは、後の分析に非常に役立ちます。

Thread.sleep

現在のスレッド (つまり、このメソッドを呼び出すスレッド) が一定期間実行を一時停止して、他のスレッドに実行を継続する機会を与えますが、オブジェクトのロックは解除されません。つまり、同期された同期ブロックがある場合でも、他のスレッドは共有データにアクセスできません。このメソッドは例外をキャッチする必要があることに注意してください。これは後続の分析に非常に役立ちます。詳細については、私の『System Learning Java High Concurrency Series 2』を参照してください。

解析処理:

javaはmainメソッドから実行されます 前述の通りスレッドが2つありますが、ここでスレッドの優先順位を変更しても意味がありません、優先順位は2つのプログラムにあります。この順序は未実行の場合のみで、このコードが実行されるとすぐにメインスレッド main が実行されます。属性変数 int b =100 の場合、ステップ 1 (Thread t = new Thread(tt); //1) を実行するときに、synchronized の使用による可視性の問題は発生しません (volatile 宣言を使用する必要はありません)。スレッド 新しい状態にあり、まだ動作を開始していません。

ステップ 2 (t.start(); //2) を実行すると、start メソッドが呼び出され、スレッドが実際に開始され、実行可能状態になります。実行可能状態とは、スレッドが実行可能であることを示し、すべてが実行可能であることを示します。準備完了ですが、必ずしもCPU上で実行しなければならないというわけではなく、実際に実行されるかどうかはサービスCPUのスケジューリングに依存します。ここで手順 3 を実行する場合、まずロックを取得する必要があります (start はネイティブ メソッドを呼び出す必要があり、使用が完了するとすべての準備が完了するため) が、CPU 上で実行する必要があるという意味ではありません。実行はサービス CPU のスケジューリングに依存します。後で run メソッドが呼び出され、m1 メソッドが実行されます)。

実際には、2 つの同期メソッドで Thread.sheep が使用されているかどうかは問題ではありません。おそらく、混乱を難しくするためだけです。ステップ 3 が実行されると、実際には子スレッドはすぐに準備が整いますが、synchronized の存在と同じオブジェクト上で動作するという事実により、子スレッドは待機する必要があります。メインメソッドの実行順序はシーケンシャルであるため、ステップ 3 の完了後にステップ 4 を完了する必要がありますが、ステップ 3 が完了しているため、サブスレッドは m1 を実行できます。

ここでは、マルチスレッド間で誰が最初にそれを取得するかという問題があります。ステップ 4 で最初にそれを取得した場合、メインスレッド b=2000 です。サブスレッド m1 がそれ​​を取得した場合、b は 1000 に割り当てられている可能性があります。を割り当てる前に、ステップ 4 で出力されます。考えられる結果は、メイン スレッド b=1000 またはメイン スレッド b=2000 です。ここでステップ 6 を削除すると、b= が最初に実行され、メイン スレッド b= が最初に実行されます。不確実である。しかし6段ある以上、どうしてもメインスレッドb=が前にあるので、1000になるか2000になるかは状況次第で、その後はb=1000で確定です。

マルチスレッドに関するいくつかの提案

スレッドも非常に貴重なので、スレッド プールを使用することをお勧めします。スレッド プールは頻繁に使用されます。後で共有します。特に重要です。そしてそれを認識する必要があります。スレッドに名前を付けます。オンラインの CPU が高い場合、高度な jstack を使用する必要があります。名前があるとさらに便利です。マルチスレッドでは、スレッド セーフの問題に特別な注意が必要です。また、jdk の使用時に不可解な問題が発生しないように、jdk がスレッド セーフであるか安全でないのかを理解する必要もあります。

後続の記事で共有するスキルもいくつかあります。マルチスレッドは特に重要かつ難しいので、皆さんにはもっと時間をかけていただけると幸いです。

マルチスレッド用のデバッグ スキル

ブレークポイントがあるため、ブレークポイントを通過するときにすべてのスレッドを停止する必要があり、このポイントが常に中断されるため、不快です。条件が揃うと止まるので便利です。

関連する推奨事項: Java 入門チュートリアル

以上がこれは Java の面接で難しい質問だと聞きましたが?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。