ホームページ Java &#&チュートリアル Java でのデッドロックを回避する方法に関するサンプル コードの共有

Java でのデッドロックを回避する方法に関するサンプル コードの共有

Jun 18, 2017 am 09:48 AM
java どうやって デッドロック 避ける

デッドロックは場合によっては回避できる。この記事では、デッドロックを回避するための 3 つのテクニックを説明します。 Java でのデッドロックの回避に関する知識に興味がある友人は、この記事から学んでください

場合によっては、デッドロックを回避できる場合があります。この記事では、デッドロックを回避するための 3 つのテクニックを説明します:

1. ロック順序

2. ロック時間制限

3. ロック順序

複数のスレッドが必要な場合順序が異なると、デッドロックが発生しやすくなります。 すべてのスレッドが同じ順序でロックを取得することが保証できれば、デッドロックは発生しません。次の例を見てください:

Thread 1:
 lock A 
 lock B
Thread 2:
  wait for A
  lock C (when A locked)
Thread 3:
  wait for A
  wait for B
  wait for C
ログイン後にコピー

スレッド (スレッド 3 など) がロックを必要とする場合、決められた順序でロックを取得する必要があります。後続のロックは、その前のロックを順番に取得した後にのみ取得できます。


たとえば、スレッド 2 とスレッド 3 は、ロック A を取得した後にのみ、ロック C の取得を試行できます (ロック A の取得は、ロック C を取得するための必須条件です)。スレッド 1 はすでにロック A を所有しているため、スレッド 2 と 3 はロック A が解放されるまで待つ必要があります。次に、B または C をロックする前に、A を正常にロックする必要があります。

順番にロックすることは、効果的なデッドロック防止メカニズムです。ただし、この方法では、使用される可能性のあるすべてのロックを事前に把握しておく (およびこれらのロックを適切に順序付けする) 必要がありますが、場合によってはそれが予測できないこともあります。


ロック時間制限

デッドロックを回避するもう 1 つの方法は、ロックを取得しようとするときにタイムアウトを追加することです。つまり、ロックを取得しようとするときにこの制限時間を超えた場合、スレッドはロックを放棄します。ロック要求。スレッドが指定された制限時間内に必要なすべてのロックを正常に取得できなかった場合、スレッドはロールバックして取得したすべてのロックを解放し、ランダムな期間待機してから再試行します。このランダムな待機時間により、他のスレッドに同じロックの取得を試行する機会が与えられ、アプリケーションはロックを取得せずに実行を継続できます (ロックがタイムアウトになった後は、実行を継続して他の作業を行ってから戻ることができます)前のロック ロジックを繰り返します)。

以下は、2 つのスレッドが異なる順序で同じ 2 つのロックを取得しようとし、タイムアウトが発生した後にロールバックして再試行する例を示しています:


 Thread 1 locks A
Thread 2 locks B
Thread 1 attempts to lock B but is blocked
Thread 2 attempts to lock A but is blocked
Thread 1's lock attempt on B times out
Thread 1 backs up and releases A as well
Thread 1 waits randomly (e.g. 257 millis) before retrying.
Thread 2's lock attempt on A times out
Thread 2 backs up and releases B as well
Thread 2 waits randomly (e.g. 43 millis) before retrying.
ログイン後にコピー

上の例では、スレッド 2 はスレッド 2 1 より小さいです。はロックを 200 ミリ秒早く再試行するため、最初に 2 つのロックを正常に取得できます。この時点で、スレッド 1 はロック A を取得しようとして待機

状態
にあります。スレッド 2 が終了すると、スレッド 1 もこれら 2 つのロックを正常に取得できます (スレッド 1 が 2 つのロックを正常に取得する前にスレッド 2 または他のスレッドがロックの一部を取得しない限り)。

ロックのタイムアウトのため、このシナリオがデッドロックであるとは考えられないことに注意してください。また、ロックを取得したスレッド (他のスレッドがタイムアウトする原因となる) がタスクを完了するまでに時間がかかる可能性もあります。
さらに、同じバッチのリソースを同時に競合するスレッドが多数ある場合、タイムアウトとロールバックのメカニズムがある場合でも、これらのスレッドは繰り返し試行してもロックを取得できない可能性があります。スレッドが 2 つしかなく、リトライ タイムアウトが 0 ~ 500 ミリ秒に設定されている場合は、この現象は発生しない可能性がありますが、スレッドが 10 または 20 個ある場合は状況が異なります。これらのスレッドが同じ再試行回数を待機する可能性がはるかに高い (または問題が発生するほど近い) ためです。 (タイムアウトやリトライの仕組みは、同時に発生する競合を避けるためのものです。ただし、スレッド数が多い場合、複数のスレッドのタイムアウトが同じか近い可能性が高いため、競合が発生してもその後、タイムアウトが同じであるため、同時に再試行が開始され、その結果、新しいラウンドの競争が発生し、新たな問題が発生します)

このメカニズムには問題があります。 Java 時間で同期された同期ブロックに設定されます。カスタム ロックを作成するか、Java5 の java.util.con

current
パッケージにあるツールを使用する必要があります。カスタム ロック クラスの作成は複雑ではありませんが、この記事の範囲を超えています。

デッドロック検出

デッドロック検出は、より優れたデッドロック防止メカニズムであり、主に順次ロックが不可能でロック タイムアウトが実現できないシナリオを対象としています。 スレッドがロックを取得するたびに、スレッドおよびロック関連のデータ構造 (マップ、グラフなど) に記録されます。さらに、スレッドがロックを要求するたびに、そのロックもこのデータ構造に記録する必要があります。

スレッドがロックの要求に失敗した場合、スレッドはロック グラフを走査してデッドロックが発生したかどうかを確認できます。たとえば、スレッド A はロック 7 を要求しますが、この時点でロック 7 はスレッド B によって保持されています。このとき、スレッド A は、スレッド A が現在保持しているロックをスレッド B が要求したかどうかを確認できます。スレッド B にそのようなリクエストがある場合、デッドロックが発生しています (スレッド A はロック 1 を所有し、ロック 7 を要求します。スレッド B はロック 7 を所有し、ロック 1 を要求します)。

もちろん、デッドロックは一般に、2 つのスレッドがお互いのロックを保持するよりも複雑です。スレッド A はスレッド B を待機し、スレッド B はスレッド C を待機し、スレッド C はスレッド D を待機し、スレッド D はスレッド A を待機します。スレッド A がデッドロックを検出するには、スレッド B によって要求されたすべてのロックを段階的に検出する必要があります。スレッド B によって要求されたロックから開始して、スレッド A はスレッド C を見つけ、次にスレッド D を見つけます。そして、スレッド D によって要求されたロックがスレッド A 自体によって保持されていることがわかりました。これは、デッドロックが発生したことを認識するときです。
それでは、デッドロックが検出された場合、これらのスレッドは何をすべきでしょうか?

考えられるアプローチは、すべてのロックを解除し、ロールバックし、ランダムな期間待機してから再試行することです。これは単純なロック タイムアウトに似ていますが、ロック リクエストがタイムアウトしたためではなく、デッドロックが発生した場合にのみロールバックが発生する点が異なります。バックオフと待機はありますが、同じロックのバッチをめぐって競合するスレッドが多数ある場合、依然としてデッドロックが繰り返し発生します。

より良い解決策は、これらのスレッドに 優先度 を設定し、1 つ (またはいくつか) のスレッドをロールバックさせ、残りのスレッドはデッドロックが発生していないかのように必要なロックを保持し続けることです。これらのスレッドに割り当てられた優先順位が固定されている場合、同じスレッドの優先順位が常に高くなります。この問題を回避するために、デッドロックが発生したときにランダムな優先順位を設定できます。

以上がJava でのデッドロックを回避する方法に関するサンプル コードの共有の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

PHP:Web開発の重要な言語 PHP:Web開発の重要な言語 Apr 13, 2025 am 12:08 AM

PHPは、サーバー側で広く使用されているスクリプト言語で、特にWeb開発に適しています。 1.PHPは、HTMLを埋め込み、HTTP要求と応答を処理し、さまざまなデータベースをサポートできます。 2.PHPは、ダイナミックWebコンテンツ、プロセスフォームデータ、アクセスデータベースなどを生成するために使用され、強力なコミュニティサポートとオープンソースリソースを備えています。 3。PHPは解釈された言語であり、実行プロセスには語彙分析、文法分析、編集、実行が含まれます。 4.PHPは、ユーザー登録システムなどの高度なアプリケーションについてMySQLと組み合わせることができます。 5。PHPをデバッグするときは、error_reporting()やvar_dump()などの関数を使用できます。 6. PHPコードを最適化して、キャッシュメカニズムを使用し、データベースクエリを最適化し、組み込み関数を使用します。 7

Java での日付までのタイムスタンプ Java での日付までのタイムスタンプ Aug 30, 2024 pm 04:28 PM

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

PHP対Python:違いを理解します PHP対Python:違いを理解します Apr 11, 2025 am 12:15 AM

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHPは、シンプルな構文と高い実行効率を備えたWeb開発に適しています。 2。Pythonは、簡潔な構文とリッチライブラリを備えたデータサイエンスと機械学習に適しています。

カプセルの量を見つけるためのJavaプログラム カプセルの量を見つけるためのJavaプログラム Feb 07, 2025 am 11:37 AM

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

PHP対Python:コア機能と機能 PHP対Python:コア機能と機能 Apr 13, 2025 am 12:16 AM

PHPとPythonにはそれぞれ独自の利点があり、さまざまなシナリオに適しています。 1.PHPはWeb開発に適しており、組み込みのWebサーバーとRich Functionライブラリを提供します。 2。Pythonは、簡潔な構文と強力な標準ライブラリを備えたデータサイエンスと機械学習に適しています。選択するときは、プロジェクトの要件に基づいて決定する必要があります。

PHP対その他の言語:比較 PHP対その他の言語:比較 Apr 13, 2025 am 12:19 AM

PHPは、特に迅速な開発や動的なコンテンツの処理に適していますが、データサイエンスとエンタープライズレベルのアプリケーションには良くありません。 Pythonと比較して、PHPはWeb開発においてより多くの利点がありますが、データサイエンスの分野ではPythonほど良くありません。 Javaと比較して、PHPはエンタープライズレベルのアプリケーションでより悪化しますが、Web開発により柔軟性があります。 JavaScriptと比較して、PHPはバックエンド開発により簡潔ですが、フロントエンド開発のJavaScriptほど良くありません。

See all articles