来自维基百科,自由的百科全书
竞争冒险(race hazard)又名竞态条件、竞争条件(race condition),它旨在描述一个系统或者进程的输出依赖于不受控制的事件出现顺序或者出现时机。此词源自于两个信号试着彼此竞争,来影响谁先输出。
此条目需要扩充。 (2015年3月22日) |
举例来说,如果计算机中的两个进程同时试图修改一个共享内存的内容,在没有并发控制的情况下,最后的结果依赖于两个进程的执行顺序与时机。而且如果发生了并发访问冲突,则最后的结果是不正确的。
当软件具有同时执行的多个代码路径时,该软件中就可能会发生竞争。如果代码路径执行所花费的时间与预期不同,它们的执行顺序也可能会与预期不同。此类意外行为将可能导致软件错误。两个程序之间也可能发生竞争,从而导致安全隐患(见下文)。
严重的竞争将可能导致无效的运行与程序错误。当进程/线程依赖于某些共享的状态时,通常会发生严重的竞争事件。在临界区块中对共享状态的操作必须互斥。不遵循此规范可能会污染共享的状态。
数据竞争是竞争危害的一种,也是许多内存模型关注的重点部分。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。
Seamless Wikipedia browsing. On steroids.