您是否注意到 Java 多線程並發示例中的競爭條件? 如何處理?

已發表: 2019-12-11

你有沒有註意到-java-multi-threading-concurrency-example中的競爭條件

前段時間我寫了一篇關於生產者消費者示例以及如何在 Java 中更好地處理讀/寫操作的文章。 同樣,在本教程中,我們將討論有關Race ConditionThread locking的內容。

如果您有以下任何問題,那麼您來對地方了:

  • Java 競爭條件示例
  • 互斥量 java 例子
  • 多線程——什麼是競爭條件?
  • 比賽條件和關鍵部分
  • 什麼是比賽條件?
  • 如何通過示例處理 Java 中的競爭條件

為什麼會出現 Java 中的競爭條件?

Java 中的競態條件發生在two or more threads嘗試修改/更新共享數據same time

讓我們看一下下面的程序邏輯:

這是一個非常簡單的銀行示例,您將在其中depositwithdraw 100 times 。 您將總共存入 $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 中,不能保證你會一直看到 Race 條件。

沒有同步塊關鍵字的 Java - Crunchify

如果您有企業級應用程序並且您正在談論每秒數百萬筆交易,那麼競爭條件可能會給您的公司帶來災難。

現在的問題是如何避免 Java 應用程序中的競爭條件?

  1. 如果競態條件是對某些共享內存數據結構的更新,則需要以適當的方式同步對數據結構的訪問和更新。
  2. 如果競爭條件是在更新數據庫中,則需要重組 SQL 以使用適當粒度級別的事務。
  3. 在投入生產之前進行負載測試並不是一個壞主意。 更多的負載可能會導致罕見的競爭條件。 最好先修復它,然後再修復它。
  4. 確保沒有要寫入的全局變量。
  5. 在 Java 中,每個對像都有一個且只有一個與之關聯的監視器和互斥鎖。 然而,單個監視器有幾個門,每個都由synchronized關鍵字指示。 當一個線程通過synchronized關鍵字時,它有效地鎖定了所有的門。
  6. 當然,如果一個線程沒有通過synchronized關鍵字,它就沒有鎖門,並且其他一些線程隨時可以免費闖入。