タイトルは次のとおりです。
パブリッククラスのtestsync2は実行可能{int b = 100;同期されたvoid m1()throws arturtedexception {b = 1000; thread.sleep(500); // 6 System.out.println( "b =" + b); } synchronized void m2()throws arturtedexception {thread.sleep(250); // 5 b = 2000; } public static void main(string [] args)throws arturnedexception {testsync2 tt = new testsync2();スレッドT = newスレッド(TT); // 1 t.Start(); // 2 tt.m2(); // 3 System.out.println( "メインスレッドb =" + tt.b); // 4} @Override public void run(){try {m1(); } catch(arturnedexception e){e.printstacktrace(); }}}このプログラムの出力結果は?
プログラム出力の結果
メインスレッドB = 2000b = 1000
または
メインスレッドB = 1000B = 1000
知識ポイントを確認してください
Javaでは、マルチスレッドプログラムを理解してデバッグするのが最も困難です。多くの場合、実行結果は想像されたように実行されません。したがって、Javaでマルチスレッドすることは非常に困難です。私が大学でC言語レベル2を取っていたときに漠然と覚えています。++の問題は何ですか、そして他の多くの優先レベルは最終出力の結果と一致します。このタイプの質問のために、ランナーの優先順位と組み合わせの質問をしたいと思います。それを裏付けることでそれを暗唱するだけですが、Javaマルチスレッドはまだよく理解される必要があります。背もたれはできません。
簡単な分析を始めましょう:
この質問には2つのスレッド(メインスレッドメイン、チャイルドスレッド)が含まれ、キーワードには同期とスレッドが含まれます。
同期されたキーワードはまだ非常に複雑です(私はそれをよく理解していないこともあるので、上記の質問にはいくつかの誤解があります)。その機能は、スレッドの同期を実現することです(スレッドの同期を実装する多くの方法があります。これは、フォローアップ記事が説明する他のもののほんの一部です。マスターダグリーのいくつかの実装は慎重に研究する必要があります)。その仕事は、同期が必要なコードをロックすることです。そうすることで、1つのスレッドのみが一度に同期ブロックに入ることができる(実際、それは悲観的な戦略です)、スレッドがセキュリティのみを記憶することを保証することです。
一般的なキーワードの使用は同期しました
上記のコードでは、同期の使用は実際に2番目のケースに属します。インスタンスメソッドに直接作用する:現在のインスタンスをロックすることと同等です。同期コードを入力する前に、現在のインスタンスのロックを取得する必要があります。
誤解の可能性
1.同期したことを何度も理解していないため、マルチスレッドによって同期された方法を操作します。 2つのスレッドが2つの異なる同期メソッドを呼び出すと、それは無関係であると考えられます。このアイデアは誤解です。インスタンスメソッドに直接作用する:現在のインスタンスをロックすることと同等です。同期コードを入力する前に、現在のインスタンスのロックを取得する必要があります。
2。同期されたメソッドが呼び出された場合。通常の方法への別の呼びかけには何の関係もありません。2人は待機の関係を持っていません。
これらは、その後の分析に非常に役立ちます。
Thread.sleep
現在のスレッド(つまり、メソッドを呼び出すスレッド)を一定期間保護し、他のスレッドに実行を継続する機会を与えますが、オブジェクトロックはリリースされません。つまり、同期化された同期が高速な場合、他のスレッドは共有データにアクセスできません。この方法は例外をキャッチする必要があることに注意してください。これは、後続の分析に非常に役立ちます。
分析プロセス
Javaはメイン方法から実行されます。 2つのスレッドがあると言われていますが、ここでスレッドの優先順位を変更しても、それは役に立たない。優先事項は、2つのプログラムがまだ実行されていない場合のみです。これで、このコードが実行されると、メインスレッドが実行されます。属性変数int b = 100の場合、同期が使用されるため(そして揮発性宣言が使用されると言う必要はありません)、ステップ1(スレッドT =新しいスレッド(TT); // 1)を実行する場合、スレッドは新しい状態にあり、まだ機能していません。 2つのステップが実行されると(t.start(); // 2)、開始メソッドが呼び出されると、スレッドは実際に開始され、実行可能な状態に入ります。実行可能な状態は、それが実行され、すべてが準備ができていることを意味しますが、CPUで実行する必要があるという意味ではありません。実際の実行があるかどうかは、サービスCPUのスケジューリングに依存します。ここで、3つのステップを実行するときは、最初にロックを取得する必要があります(スタートがネイティブメソッドを呼び出す必要があり、使用が完了した後はすべてが準備ができているためですが、CPUで実行する必要があるという意味ではありません。実際の実行があるかどうかは、サービスCPUのスケジューリングに依存し、実行方法が呼び出され、M1メソッドが実行されます)。実際、2つの同期されたメソッドのthread.sheepがかどうかは関係ありませんが、おそらく混乱に困難を加えるでしょう。 3つのステップが実行されると、子スレッドは実際にすぐに準備ができていますが、同期されたものが存在し、同じオブジェクトとして機能するため、子スレッドは待たなければなりません。メインメソッドの実行順序は順次実行されるため、4番目のステップに到達する前にステップ3が実行された後に完了する必要があります。ステップ3の実行が完了するため、子スレッドはM1を実行できます。ここでは、誰が最初にマルチスレッドを取得するかという問題があります。最初に4つのステップが取得された場合、メインスレッドB = 2000。子スレッドM1が取得された場合、Bが1000に割り当てられているか、4つのステップが割り当てられる前に割り当てられている可能性があります。ここで6つのステップが削除されている場合、b = b =実行前に実行し、メインスレッドb =が不確かです。ただし、6つのステップが存在するため、何があっても、メインスレッドB =が前にあるため、1000または2000に等しい場合は状況に依存します。その後、B = 1000は間違いなく固定されます。
マルチスレッドに関するいくつかの提案
後続の記事で共有するためのヒントもいくつかあります。マルチスレッドは特に重要で困難です。みんながもっと時間を費やすことを願っています。
マルチスレッドのためのいくつかのデバッグ技術
ブレークポイントのため、すべてのスレッドはブレークポイントを通過するときに停止する必要があります。これにより、この点は絶えず中断されます。これは非常に不快です。 eclispeには条件付きブレークポイントがあり、条件が満たされたときに停止できますので、これは便利です。
要約します
上記は、編集者があなたに紹介した歴史上最も難しいJavaインタビューの質問です。それがあなたに役立つことを願っています。ご質問がある場合は、メッセージを残してください。編集者は時間内に返信します。 wulin.comのウェブサイトへのご支援ありがとうございます!