競爭危害

競爭危害(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).