競爭危害(race hazard)又名競態條件、競爭條件(race condition),它旨在描述一個系統或者進程的輸出依賴於不受控制的事件出現順序或者出現時機。此詞源自於兩個訊號試著彼此競爭,來影響誰先輸出。
此條目需要擴充。 (2015年3月22日) |
舉例來說,如果電腦中的兩個行程同時試圖修改一個共享主記憶體的內容,在沒有並行控制的情況下,最後的結果依賴於兩個行程的執行順序與時機。而且如果發生了並行訪問衝突,則最後的結果是不正確的。
實例
- 計算機記憶體或者磁碟裝置裡,如果同時發出大量數據指令的時候,競爭危害可能發生。計算機嘗試覆蓋相同或者舊的數據,而此時舊的數據仍在被讀取。結果可能是下面的一個或者多個情況:機器當機、出現非法操作並結束程式、錯誤的讀取舊數據、或者錯誤的寫入新數據。
- 網路上,競爭危害會在:多使用者同時試圖訪問同一個可用訊息通道時,產生。在系統同意訪問前沒有計算機能得到訊息通道被佔用的提醒。統計上說這種情況通常發生在極端長延遲時間的網路裡,譬如地球同步衛星。解決之道是使用者預先產生優先級列表。然而駭客可以利用這種競爭危害取得非法訪問網路的權利。
- 數位電路,由於邏輯部件輸出對輸入有一個回應延遲,因此可能在輸出上出現一個不希望有的脈衝訊號。被稱為Electronics glitch。使用卡諾圖以發現並消除這類問題。
![Thumb](http://upload.wikimedia.org/wikipedia/commons/thumb/7/78/Race_condition.svg/262px-Race_condition.svg.png)
軟體設計
當軟體具有同時執行的多個代碼路徑時,該軟體中就可能會發生競爭。如果代碼路徑執行所花費的時間與預期不同,它們的執行順序也可能會與預期不同。此類意外行為將可能導致軟體錯誤。兩個程式之間也可能發生競爭,從而導致安全隱患(見下文)。
嚴重的競爭將可能導致無效的執行與程式錯誤。當行程/執行緒依賴於某些共享的狀態時,通常會發生嚴重的競爭事件。在臨界區段中對共享狀態的操作必須互斥。不遵循此規範可能會污染共享的狀態。
資料競爭是競爭危害的一種,也是許多主記憶體模型關注的重點部分。C11與C++11標準所定義的主記憶體模型規定含有資料競爭情況的C或C++程式帶有未定義行為。[1][2]
競爭可能會難以復現/除錯,因為取決於干擾執行緒的相對執行時機,其產生的結果是非確定性的。當在除錯模式下執行、附加額外的紀錄檔記錄或除錯器時,問題可能不會出現。這種在除錯期間消失的錯誤通常被稱為海森堡bug。因此,最好在設計環節多加注意以避免出現競爭。
假設有兩個執行緒,各自會將同一個全域數值變數加1。理想狀態下,它們會以這樣的順序執行:
執行緒1 | 執行緒2 | 資料值 | |
---|---|---|---|
0 | |||
讀取(0) | ← | 0 | |
增加(1) | 0 | ||
寫回 | → | 1 | |
讀取(1) | ← | 1 | |
增加(2) | 1 | ||
寫回 | → | 2 |
在上文的理想狀態下,執行的結果為預期的2。但是,如果兩個執行緒在沒有鎖定或通過號誌同步的情況下同時執行,執行的結果將可能出錯。如下展示了另一種情況:
執行緒1 | 執行緒2 | 資料值 | |
---|---|---|---|
0 | |||
讀取(0) | ← | 0 | |
讀取(0) | ← | 0 | |
增加(1) | 0 | ||
增加(1) | 0 | ||
寫回 | → | 1 | |
寫回 | → | 1 |
在這種情況下,因為執行緒的增加操作沒有互斥,導致最終結果為1,而不是預期的2。