Javaマルチスレッド同時実行の例の競合状態に気づきましたか? どのように対処しますか?

公開: 2019-12-11

have-you-noticed-race-condition-in-java-multi-threading-concurrency-example

しばらく前に、プロデューサーコンシューマーの例と、Javaで読み取り/書き込み操作をより適切に処理する方法に関する記事を書きました。 同様に、このチュートリアルでは、競合Race ConditionThread lockingについて説明します。

以下の質問のいずれかがある場合は、適切な場所にいます。

  • Javaの競合状態の例
  • mutexjavaの例
  • マルチスレッド–競合状態とは何ですか?
  • 競合状態とクリティカルセクション
  • 競合状態とは何ですか?
  • 例を使用してJavaで競合状態を処理する方法

Javaで競合状態が発生するのはなぜですか?

Javaの競合状態は、 two or more threadsが共有データをsame time変更/更新しようとしたときに発生します。

以下のプログラムロジックを見てみましょう。

これは非常に単純な銀行の例で、金額を100 times depositたりwithdrawたりします。 $ 100の合計100回= $ 100 x 100 = $ 10,000をデポジットし、$ 50の合計100回= $ 50 x 100 = $ 5,000を引き出します。 プログラムの完了時に、銀行に5000ドルが必要です。

手順は次のとおりです。

  1. クラスCrunchifyRaceCondition.javaを作成します
  2. クラスCrunchifyTransaction.javaを作成します
  3. クラスCrunchifyBankAccount.javaを作成します
  4. クラスCrunchifyRaceConditionを実行すると、入金と出金のループが100回開始されます。
  5. with Synchronized block実行して結果を確認します
  6. without Synchronized blockで実行して結果を確認します

CrunchifyRaceCondition.java

CrunchifyTransaction.java

CrunchifyBankAccount.java

上記の24行目と34行目を確認してください。 そのSynchronizedキーワードを保持し、プログラムを実行します。 下の画像に表示されているように、正しい結果が表示されるはずです。

Java同期ブロックキーワード-Crunchify

次に、24行目と34行目から同期キーワードを削除し、同じプログラムを実行します。

問題を確認するには、このプログラムを複数回実行する必要がある場合があります。 Javaでは、競合状態が常に表示される保証はありません。

同期ブロックキーワードのないJava-Crunchify

エンタープライズレベルのアプリケーションがあり、1秒あたり数百万のトランザクションについて話している場合、競合状態は会社に災害を引き起こす可能性があります。

ここで問題となるのは、Javaアプリケーションで競合状態を回避する方法です。

  1. 競合状態が一部の共有メモリ内データ構造の更新にある場合は、データ構造へのアクセスと更新を適切な方法で同期する必要があります。
  2. 競合状態がデータベースの更新にある場合は、適切なレベルの粒度でトランザクションを使用するようにSQLを再構築する必要があります。
  3. 本番環境に移行する前に負荷テストを行うことは悪い考えではありません。 より多くの負荷が発生すると、まれな競合状態が発生する可能性があります。 後で修正するのではなく、前に修正することをお勧めします。
  4. 書き込むグローバル変数がないことを確認してください。
  5. Javaでは、すべてのオブジェクトに1つだけのモニターとミューテックスが関連付けられています。 単一のモニターにはいくつかのドアがありますが、それぞれがsynchronizedキーワードで示されています。 スレッドがsynchronizedキーワードを通過すると、すべてのドアが効果的にロックされます。
  6. もちろん、スレッドがsynchronizedキーワードを通過しない場合、そのスレッドはドアをロックしておらず、他のスレッドはいつでもフリーバージインされます。