この記事では主に Java スレッド セーフティの基本概念の分析を紹介します。これが参考になり、必要な友人がさらに学ぶことができることを願っています。
Java スレッド セーフについての初期理解。一般に、JAVA スレッド セーフとは、マルチスレッド オペレーティング環境における Java オブジェクトの特性を指します。これは、(特殊な呼び出し状況とは異なり) 通常の状態で各呼び出しが正しい論理結果を取得できることを意味します。基本的に、同期制御ロジックはオブジェクトのメソッド動作に追加され、呼び出し元は追加の同期制御なしでオブジェクトを安全かつ確実に使用できます。
1. スレッドセーフの定義
複数のスレッドがオブジェクトにアクセスする場合、実行時環境でこれらのスレッドのスケジューリングと代替実行を考慮する必要がない場合、追加の同期は必要ありません。呼び出し側で他の調整操作が実行され、このオブジェクトを呼び出すことで正しい結果が得られる場合、このオブジェクトはスレッドセーフです。この定義は非常に厳密で、すべてのスレッドセーフ コードには 1 つの特性があることが必要です。つまり、コード自体が必要な正確性保証手段をすべてカプセル化しているため、呼び出し元はマルチスレッドの問題を気にする必要がなく、実装する必要もありません。 Rehe は、正しい呼び出しを確実にマルチスレッド化するための対策を講じています。
2. Java 言語のスレッド セーフ
スレッド セーフをより深く理解するために、スレッド セーフの「セキュリティの強さ」に応じて、スレッド セーフを不変、絶対的なものに分けて説明します。スレッド セーフ、相対スレッド セーフ、スレッド互換性、スレッド拮抗性。
2.1 不変
jDK1.5 以降、不変オブジェクトは、オブジェクトのメソッド実装であっても、メソッドの呼び出し元であっても、スレッドセーフでなければなりません。安全性の保証。final キーワードによって変更されたメジャー、プロパティ、オブジェクト、またはメソッドの外部に表示される状態は決して変更されません。共有データが基本データ型の場合、定義時に Final キーワードを使用することで不変であることが保証されます。たとえば、String クラス オブジェクトは典型的な不変オブジェクトです。substring()、replace()、および concat() を呼び出した場合、これらのメソッドは元の値に影響を与えず、新しく構築された文字列オブジェクトのみを返します。
2.2 相対スレッド セーフ
相対スレッド セーフは、通常、スレッド セーフと呼ばれるもので、このオブジェクトの個々の操作がスレッド セーフであることを保証する必要があります。 Vector、HashTable など、Java のほとんどのスレッドセーフ クラスはこのタイプに属します。
2.3 スレッド互換性
スレッド互換性とは、オブジェクト自体はスレッドセーフではありませんが、呼び出し側で同期手段を正しく使用することで、オブジェクトが並行環境で安全に使用できることを意味します。
2.3 スレッドの対抗
スレッドの対抗とは、呼び出し元が同期手段を使用しているかどうかに関係なく、マルチスレッド環境で同時に使用できないコードを指します。 Java 言語は本質的にマルチスレッドであるため、スレッド対立などマルチスレッドを排除するコードはほとんど出現しません。一般的なスレッド反対操作には、Thread クラスの stop() メソッドとresume() メソッド、System.setIn() などが含まれます。
3. スレッドセーフな実装方法
3.1 相互排他同期
同期とは、同時実行性の正確性を保証する最も一般的な方法です。マルチスレッド共有アクセス時データを同時に使用するには、共有データが同時に 1 つのスレッドによってのみ使用されるようにしてください。ミューテックスは同期を実現する手段であり、クリティカル セクション、ミューテックス、セマフォが相互排他を実装する主な方法です。相互排他が原因、同期が結果、相互排他が方法、同期が目的です。
Java では、最も基本的な相互排他的な同期方法は synchronized キーワードです。さらに、java.util.concurrent パッケージのリエントラント ロック (ReentrantLock) を使用して同期を実現することもできます。使用方法は非常に似ていますが、コードの記述にはいくつかの違いがあります。1 つは API レベルでの相互排他ロック (lock() メソッドとunlock() メソッドは try/finally ステートメント ブロックで完了します) です。ネイティブ構文レベルの相互排除ロック。ただし、リエントラント ロックには、同期ロックと比較して次の 3 つの特徴があります:
待機は割り込み可能: ロックを保持しているスレッドが長時間ロックを解放しない場合、待機スレッドは待機を放棄し、代わりに他の処理を選択できることを意味します。 . 割り込み機能 実行に非常に時間がかかる同期ブロックを処理する場合に便利です。
達成可能な公平なロック: 公平なロックとは、複数のスレッドが同じロックを待機しているときに、ロックを申請した時間順に従って順番にロックを取得する必要があることを意味します。不公平なロックはこれを保証しません。同期されたロックは不公平であり、再入可能ロックもデフォルトでは不公平ですが、ブール値を使用してコンストラクターを介して公平なロックの使用を要求できます。
ロックは複数の条件にバインド可能: これは、再入可能なロック オブジェクトを同時に複数の Condition オブジェクトにバインドできることを意味し、同期では、ロック オブジェクトの wait() メソッドと、notify() または NoticeAll() メソッドを実装できます。暗黙的 条件が複数の条件に関連付けられている場合は、追加のロックを追加する必要があります。ただし、再入可能なロックの場合は、これを行う必要はありません。 newCondition() メソッドを複数回呼び出すだけです。
3.2 ノンブロッキング同期
相互排他的同期の最も重要な問題は、スレッドのブロックとウェイクアップによって引き起こされるパフォーマンスの問題であると私は常々思っています。適切な同期手段を講じないと問題が発生する可能性があります。しかし、別のオプションもあります。それは、競合検出に基づく楽観的同時実行戦略です。簡単に言うと、共有データをめぐって競合するスレッドが存在しない場合、操作は成功します。このオプティミスティック同時実行戦略の多くの実装では、スレッドを一時停止する必要がないため、ノンブロッキング同期と呼ばれます。
概要
以上がJava におけるスレッド セーフの基本概念の分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。