競爭危害(race hazard)又名競態條件競爭條件(race condition),它旨在描述一個系統或者進程的輸出依賴於不受控制的事件出現順序或者出現時機。此詞源自於兩個訊號試着彼此競爭,來影響誰先輸出。

舉例來說,如果電腦中的兩個行程同時試圖修改一個共用主記憶體的內容,在沒有並行控制的情況下,最後的結果依賴於兩個行程的執行順序與時機。而且如果發生了並行訪問衝突,則最後的結果是不正確的。

競爭危害常見於不良設計的電子系統,尤其是邏輯電路。但它們在軟件中也比較常見,尤其是有採用多線程技術的軟件。

實例

編輯
  1. 計算機記憶體或者磁碟裝置裏,如果同時發出大量數據指令的時候,競爭危害可能發生。計算機嘗試覆蓋相同或者舊的數據,而此時舊的數據仍在被讀取。結果可能是下面的一個或者多個情況:機器死機、出現非法操作並結束程式、錯誤的讀取舊數據、或者錯誤的寫入新數據。
  2. 網絡上,競爭危害會在:多用戶同時試圖訪問同一個可用訊息通道時,產生。在系統同意訪問前沒有計算機能得到訊息通道被佔用的提醒。統計上說這種情況通常發生在極端長延遲時間的網絡裏,譬如地球同步衛星。解決之道是用戶預先產生優先級列表。然而黑客可以利用這種競爭危害取得非法訪問網絡的權利。
  3. 數碼電路,由於邏輯部件輸出對輸入有一個響應延遲,因此可能在輸出上出現一個不希望有的脈衝訊號。被稱為Electronics glitch。使用卡諾圖以發現並消除這類問題。
 
邏輯電路中的競態條件.這裏,∆t1與∆t2表示邏輯單元的傳播延遲.當輸入值(A)改變,電路輸出有一個很短的峰持續(∆t1+∆t2) - ∆t2 = ∆t1.

軟件設計

編輯

當軟件具有同時執行的多個代碼路徑時,該軟件中就可能會發生競爭。如果代碼路徑執行所花費的時間與預期不同,它們的執行順序也可能會與預期不同。此類意外行為將可能導致軟件錯誤。兩個程式之間也可能發生競爭,從而導致安全隱患(見下文)。

嚴重的競爭將可能導致無效的執行與程式錯誤。當行程/線程依賴於某些共用的狀態時,通常會發生嚴重的競爭事件。在臨界區段中對共用狀態的操作必須互斥。不遵循此規範可能會污染共用的狀態。

數據競爭是競爭危害的一種,也是許多主記憶體模型關注的重點部分。C11C++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。

參見

編輯

外部連結

編輯
  1. ^ ISO/IEC 9899:2011 - Information technology - Programming languages - C. Iso.org. [2018-01-30]. (原始內容存檔於2011-12-27). 
  2. ^ ISO/IEC 14882:2011. ISO. 2 September 2011 [3 September 2011]. (原始內容存檔於2013-01-29).