私は勉強していますJavaスレッドとデッドロック、デッドロックの例を理解していますが、それを防ぐために従うべき一般的なルールがあるのだろうか。
私の質問は、デッドロックを防ぐためにJavaのソースコードに適用できるルールまたはヒントがあるかどうかです。はいの場合、実装方法を説明できますか?
私の頭からいくつかの簡単なヒント
カプセル化、カプセル化、カプセル化!ロックで最も危険な間違いは、ロックを世界に公開することです(公開すること)。オブジェクトを知らなくても誰でもロックを取得できるため、これを行うと何が起こるかわかりません(これは、this
をロックしない理由でもあります)。ロックをプライベートにすると、完全に制御でき、管理しやすくなります。
ConcurrentLinkedQueue
の代わりにArrayList
を使用します)読み、理解してくださいJava:Concurrency and Practice。これは、デッドロックを回避するための「ヒント」ではありません。デッドロックを回避するためのいくつかのヒントを知っていて、しばしばデッドロックを回避する開発者を雇うことは決してありません。並行性を理解することです。幸いなことに、このトピックに関する包括的な中級レベルの本があるので、読んでみてください。
設計上の選択肢が与えられた場合、キューのプッシュ/ポップにロックのみがある場所でメッセージの受け渡しを使用します。これは常に可能とは限りませんが、可能であれば、デッドロックはほとんどありません。あなたはまだそれらを手に入れることができますが、本当に一生懸命努力する必要があります:)
デッドロックの防止に関しては、1つの大きなルールがあります。
コードに複数のロックを設定する必要がある場合は、全員が常に同じ順序でロックを取得するようにしてください。
ただし、コードをロックから解放することは、ほとんど常に目標です。不変オブジェクトまたはスレッドローカルオブジェクトとロックフリーのデータ構造を使用して、それらを取り除くことができます。
これは、デッドロックの典型的な例です。
public void methodA()
{
//...
synchronized(lockA)
{
//...
synchronized(lockB)
{
//...
}
}
}
public void methodB()
{
//...
synchronized(lockB)
{
//...
synchronized(lockA)
{
//...
}
}
}
このメソッドは、多くのスレッドから呼び出された場合、おそらく大きなデッドロックを作成します。これは、オブジェクトが異なる順序でロックされているためです。これは、デッドロックの最も一般的な理由の1つです。したがって、それらを回避する場合は、ロックが順番に取得されるであることを確認してください。
Javaのデッドロックは、2つ以上のスレッドが永久にブロックされるプログラミング状況です。Java少なくとも2つのスレッドと2つ以上のリソースでデッドロック状況が発生します。
Javaでデッドロックを検出するには、アプリケーションのJavaスレッドダンプを調べる必要があります。VisualVMプロファイラーまたはjstackユーティリティを使用。
デッドロックを分析するには、状態が[〜#〜] blocked [〜#〜]のスレッドと、それが存在するリソースを探す必要があります。ロックを待っています。すべてのリソースには一意のIDがあり、これを使用して、オブジェクトのロックをすでに保持しているスレッドを見つけることができます。
これらは、ほとんどのデッドロック状態を回避できるガイドラインの一部です。
ネストされたロックを避けます。これがデッドロックの最も一般的な理由です。別のリソースを既に保持している場合は、ロックしないでください。1つのオブジェクトロックのみで作業している場合、デッドロックを取得することはほとんど不可能です。
必要なものだけをロックします。オブジェクト全体をロックするのではなく、オブジェクトの特定のフィールドをロックするように、目的にかなう場合。
無期限に待たないでください。
synchronized
ブロックまたは Lock sを使用します。synchronized
コードブロックのみを使用している場合、ロックが特定の順序で取得/解放されていることを確認してください。Lock
API関連するSEの質問:
Javaでsynchronized(this)を避けますか?