マルチスレッドでの隠されたインタビューの質問

誰もが就職活動で面接を経験したことがあります-とにかく経験したことはありません

誰もが面接に精通していて、誰もが仕事を見つけたいと思っています。今、仕事を探すには必ず面接が必要です。しかし、面接では、面接官があなたが必要な人かどうかを確認するために質問をすることがよくあります。

学習したJavaを使用して理想的な仕事を見つけたいと考えています。Javaではマルチスレッドが非常に重要なので、マルチスレッドに隠されている面接の質問について話しましょう。

1. Javaマルチスレッドのいくつかの実装方法、スレッドセーフとは何ですか?

Javaマルチスレッドを実装する主な方法は4つあります。

1. Threadクラスを継承します。スレッドを開始する唯一の方法は、Threadクラスのstart()メソッドを使用し、インスタンスの後にstart()メソッドを呼び出して開始することです。

2. Runnableインターフェース実装し、run()メソッドを書き直します

3.呼び出し可能インターフェイスを実装します

4. FutrueTaskラッパーを介して

スレッドセーフとは、スレッドアクセス中にロックメカニズムを使用することです。スレッドがこのタイプの特定のデータにアクセスすると、そのスレッドは保護され、他のスレッドはアクセスできなくなります。他のスレッドは、スレッドがデータを読み取るまでしか使用できず、データはありません。不整合またはデータの汚染が表示されます。

第二に、同期の特徴

2.1アトミシティ

いわゆるアトミック性とは、1つの操作または複数の操作を指し、すべてが実行され、実行プロセスが何らかの要因によって中断されないか、実行されません。

Javaでは、基本データ型の変数の読み取りおよび代入操作はアトミック操作です。つまり、これらの操作は、実行されても実行されなくても、中断することはできません。ただしi++、などのi+=1操作文字はアトミックではありません。読み取り、計算、割り当てなどのいくつかの操作に分割されます。これらの手順が完了する前に元の値が割り当てられている可能性があるため、最終的な割り当てによって書き込まれたデータはダーティです。 。データ、原子性は保証できません。

同期によって変更されたクラスまたはオブジェクトのすべての操作はアトミックです。これは、操作を実行する前にクラスまたはオブジェクトのロックを取得する必要があり、実行が完了するまでロックを解放できないためです。中間プロセスを中断することはできません(廃止されたstop()メソッドを除く)。つまり、アトミック性が保証されます。

注意!インタビューでは、同期と揮発性の比較についてよく尋ねます。2つの機能の最大の違いは原子性です。揮発性には原子性がありません。

2.2可視性

可視性とは、複数のスレッドがリソースにアクセスするときに、リソースのステータスと値の情報が他のスレッドに表示されることを意味します。

同期と揮発性の両方に可視性があります。同期がクラスまたはオブジェクトをロックする場合、スレッドはクラスまたはオブジェクトにアクセスする場合、最初にロックを取得する必要があり、このロックの状態は他のスレッドに表示され、ロックを解放する前に、変数の変更は、リソース変数の可視性を確保するためにメインメモリにフラッシュされます。スレッドがロックを占有している場合、他のスレッドはロックがロックプールで解放されるのを待つ必要があります。

volatileの実装も同様です。volatileによって変更された変数は、値を変更する必要があるときはいつでもメインメモリをすぐに更新します。メインメモリは共有され、すべてのスレッドに表示されるため、他のスレッドによって読み取られた変数が常に最新であることが保証されます。値。可視性。

2.3秩序

順序値プログラムが実行される順序は、コードに従って順番に実行されます。

同期揮発性の両方が順序付けられます。Javaではコンパイラとプロセッサが命令を再配置できますが、命令の再配置は単一スレッドの順序には影響しません。複数のスレッドの同時実行の順序には影響します。同期により、各瞬間に1つのスレッドのみが同期コードブロックにアクセスするようになります。これにより、スレッドが同期コードブロックを順番に実行することも決定され、順序が保証されます。

2.4再入可能

同期ReentrantLockはどちらも再入可能ロックです。スレッドが別のスレッドによって保持されているオブジェクトロックの重要なリソースを操作しようとすると、ブロックされた状態になりますが、スレッドがそれ自体によって保持されているオブジェクトロックの重要なリソースを再度要求すると、この状況は再入可能ロックになります。素人の言葉で言えば、それはロックを所有するスレッドがまだ繰り返しロックを申請できることを意味します。

同期の使用法

Synchronizedは静的メソッドやメンバー関数を変更でき、コードブロックを直接定義することもできますが、最終的な分析では、ロックされているリソースは2種類のみです。1つはオブジェクトで、もう1つはクラスです。

Javaの開発プロセスでは、いくつかのデザインパターンに精通していることがよくあります。デザインパターンでは、シングルトンデザインパターンが最初に接触するデザインパターンであり、一般的に使用されるデザインパターンでもあります。シングルトンデザインパターンは、空腹のスタイルと怠惰なスタイルの2つのタイプに分けられます。これらの2つの怠惰なスタイルには、スレッドの不安定な問題があります。

3.レイジースタイルのスレッドは安全ではありません。スレッドセーフに変更されました

      スレッドを安全にする方法はいくつかあります。これらのメソッドの中で、同期コードブロックと同期メソッドは、スレッドセーフを解決するために最も一般的に使用されるメソッドです。

      ここでは、シングルトンデザインパターンの怠惰な男性のレビューを紹介します。怠惰な男性が何であるかわからないのではないかと思います。

      怠惰な男を書くための手順

      ①民営化クラスの建設者

      ②初期化せずに現在のクラスオブジェクトを宣言する

      ③このオブジェクトも静的として宣言する必要があります

      ④現在のクラスのオブジェクトを返すためのパブリック静的メソッドを提供します

class Singleton{
    //①私有化类的构造器
    private Singleton{

    }
    //②内部提供当前类的实例
    //③此实例必须静态化
    private static Singleton single;
    //④提供公共的静态方法,返回当前类的对象
    public static Singleton getSingleton(){
       if(single == null){
        single = new Singleton();
        }
        return single;
    }
}

    シングルトンデザインパターンでレイジースタイルを確認しました。上記のレイジースタイルはスレッドセーフではありません。以下では、同期コードブロックメソッドを使用してレイジースタイルをスレッドセーフに変更します。

     確かに、シングルトンデザインパターンの怠惰な流れをご存知の方もいらっしゃるので、怠惰になります。

class Singleton{
    //①私有化类的构造器
    private Singleton{

    }
    //②内部提供当前类的实例
    //③此实例必须静态化
    private static Singleton single = null;
    //④提供公共的静态方法,返回当前类的对象
    public static Singleton getSingleton(){
        synchronized(Singleton.class){
       if(single == null){
        single = new Singleton();
        }
        return single;
       }
    }
}

   ただし、この方法では怠惰な人をスレッドセーフに変えることができますが、効率が遅すぎて、すべてが効率的です。この方法で十分です!

Javaのマルチスレッドでは、同期モニターについて聞いたことがあるでしょう。同期モニターと同期コードブロックは分離できません。同期モニターは一般にロックと呼ばれます。スレッドセーフを解決する場合、ロックを使用してスレッドセーフの問題を解決することもできます。

第四に、syschronizedとLockの類似点と相違点は?

       類似点:どちらもスレッドセーフの問題を解決できます

       違い:同期メカニズムは、対応する同期コードを実行した後、同期モニターを自動的に解放します

                     ロックは手動で同期を開始する必要があり(lock())、同期の終了も手動で実装する必要があります(unlock())

      同期とロックの比較

      1.ロックは表示ロック(手動でロックを開閉します。ロックを閉じることを忘れないでください)、同期は暗黙のロックであり、スコープ外に自動的に解放されます。

      2.ロックにはコードブロックロックのみがあり、同期にはコードブロックロックとメソッドロックがあります

      3.ロックロックを使用すると、JVMはスレッドのスケジュールに費やす時間が少なくなり、パフォーマンスが向上します。また、スケーラビリティが向上しています(より多くのサブカテゴリを提供します)

jdk 5.0では、ロックはスレッドセーフを解決するための新しい方法であり、将来的に開発で使用することがよくあります。開発中のほとんどの企業で使用されるjdkは1.8ですが、時代の進歩とともに、多くのオプションもあります。開発における問題を解決するため。Javaマルチスレッドには多くのメソッドがあり、その中でsleep()メソッドとwait()メソッドが頻繁に使用されるメソッドです。それらが正常に呼び出されると、スレッドはブロックされます。

5つ目は、sleep()とwait()の類似点と相違点です。

       同じ点:メソッドが実行されると、現在のスレッドはブロッキング状態に入ることができます

       差: 

                   1)2つのメソッドは異なる位置で宣言されます。sleep()はThreadクラスで宣言され、wait()はオブジェクトで宣言されます。

                   2)呼び出し要件は異なります。sleep()は、必要な任意のシーンで呼び出すことができます。wait()は同期コードブロックで呼び出す必要があります

                   3)同期モニターを解放するかどうかについて:同期コードブロックまたは同期メソッドで両方のメソッドが使用されている場合、sleep()は同期モニターを解放せず、wait()は同期モニターを解放します。

このシナリオでは、 Jiu Kuanは、マルチスレッドスレッド通信に表示されると考えています。スレッドをゆっくりキューに入れたい場合は、2つのメソッドを使用し、notify()を使用してスレッドをウェイクアップできます。複数のステートメントが同じスレッドでデータを共有するために動作している場合、1つのスレッドは複数のステートメントの一部のみを実行し、別のスレッドはステートメントが完了する前にその実行に参加します。共有データにつながるエラー。複数の操作のデータを共有するステートメントの場合、実行できるスレッドは1つだけです。実行中は、他のスレッドは実行に参加できません。Javaは、マルチスレッドのセキュリティ問題に対する専門的なソリューションを提供します。同期メカニズム同期ロックメカニズムは、タスクで使用されるときにリソースをロックすることです。特定のリソースにアクセスする最初のタスクは、このリソースをロックして、ロックが解除されるまで他のタスクがアクセスできないようにする必要があります。ロックが解除されると、別のタスクがリソースをロックして使用できます。

6. Javaは、いくつかの方法でスレッドセーフの問題をどのように解決しますか?

1.コードブロックを同期します

          同期コードブロックのロックは、自分で指定できます。多くの場合、thisまたはクラスname.classとして指定します。任意のオブジェクトを同期ロックとして使用でき、すべてのオブジェクトに1つのロック(モニター)が自動的に含まれます。
たとえば、マルチスレッドはRunnableインターフェイスを実装することで実装されます。複数のスレッドがオブジェクトを共有するため、現時点では同期ロックは任意のオブジェクトにすることができます。Threadを継承する方法を使用してマルチスレッドを実装する場合、複数のスレッドは同じオブジェクトではないため、現時点ではクラス名.classまたは静的オブジェクトのみを使用できます。全体として、同じリソースを使用する複数のスレッドがロックを共有することを確認する必要があります。これは非常に重要です。そうしないと、共有リソースのセキュリティが保証されません。

2.同期方法

  • 同期メソッドロック:静的メソッド(クラス名.class)、非静的メソッド(this)
  • スレッドクラスのすべての静的メソッドは同じロック(クラス名.class)を共有し、すべての非静的メソッドは同じロック(this)を共有します

3.ロック(ロック)

JDK 5.0以降、Javaはより強力なスレッド同期メカニズムを提供します。同期は同期ロックオブジェクトを明示的に定義することで実現されます。同期ロックは、ロックオブジェクトを使用して機能します。java.util.concurrent.locks.Lockインターフェースは、共有リソースにアクセスするために複数のスレッドを制御するためのツールです。ロックは、共有リソースへの排他的アクセスを提供します。一度に1つのスレッドのみがLockオブジェクトをロックできます。スレッドが共有リソースへのアクセスを開始する前に、Lockオブジェクトを取得する必要があります。ReentrantLockクラスは、同期と同じ同時実行性とメモリセマンティクスを持つLockを実装します。スレッドセーフ制御の実現では、ReentrantLockがより一般的に使用され、明示的にロックおよびロックを解放できます。

ロックは明示的なロック(手動でロックを開閉します。ロックを閉じることを忘れないでください)、同期は暗黙的なロックであり、スコープ外に自動的に解放されます。ロックロックを使用すると、JVMはスレッドのスケジュールに費やす時間が短縮され、パフォーマンスが向上します。また、スケーラビリティが向上しています(より多くのサブカテゴリを提供します)

7.揮発性の原理と機能、それはロックを置き換えることができますか?

       Volatileは軽量の同期であり、マルチプロセッサ開発における共有変数の「可視性を保証します可視性とは、あるスレッドが共有変数を変更すると、別のスレッドが変更された値を読み取ることができることを意味します。フィールドが揮発性として宣言されている場合、Javaマルチスレッドメモリの強迫観念により、すべてのスレッドがこの変数の値に一貫性があることを確認できます。いくつかの特徴があります。

    Volatle は、複合操作の原子性を保証できませんJavaは、基本的なデータ型変数のプロパティのみを保証します。代入演算はアトミックです。もちろん、ロックと同期を使用してアトミック性を確保できます。厳密に言えば、単一の揮発性変更の読み取り/書き込みはアトミックですが、volatile ++と同様の複合操作はアトミックではありません

    Volatileは可視性を保証できます。変数がvolatileによって変更された場合、スレッドローカルメモリが無効であることを意味します。スレッドが共有変数を変更すると、メインメモリに更新されます。他のスレッドが共有変数を読み取ると、メインメモリから直接読み取ります。もちろん、同期とロックの両方で可視性を保証できます。

     Volatileは、順序保証し、命令の並べ替えを禁止できます。

要約すると、volatileはスレッドの可視性を保証し、ある程度の順序を提供できますが、アトミック性を保証することはできません。JVMの下部では、「メモリバリア*」を使用してvolatileが実装されます。

使用シナリオでは、軽量ロック変数は同期を置き換えることはできません。ただし、限られた状況では、vlaile変数を使用してロックを置き換えることもできます。vlatile変数を指定する必要があります。理想的なスレッドの安全性は、次の2つの条件を満たす必要があり
    ます。変数への書き込み操作は現在の値に依存しません。

    この変数は、他の変数との不変条件には含まれていません。

 

  推奨

  推奨ブラウザ:Google Chrome

  推奨されるJava環境:Eclipse、IDEA

  今週の推奨学習:HTMLとCSS

  推奨される学習ビデオリンク:https:  //www.bilibili.com/video/BV1CK411G7m4?from = search&seid = 9778818247834758128

  推奨されるHTML環境:VScode(Visual Studio Code)

 

 

おすすめ

転載: blog.csdn.net/weixin_52011642/article/details/110570074