我经常在并发编程的上下文中发现这些术语被使用。它们是同一个东西还是不同的东西?
我经常在并发编程的上下文中发现这些术语被使用。它们是同一个东西还是不同的东西?
不,它们不是同一件事。它们也不是彼此的子集。它们既不是必要条件也不是充分条件。
数据竞争的定义非常清晰,因此可以进行自动化发现。当两个不同线程的两个指令访问同一内存位置时,如果这些访问中至少有一个是写入操作,并且没有同步机制强制规定这些访问之间的任何特定顺序,则会发生数据竞争。
竞态条件是一种语义错误。它是由于事件的时间安排或排序出现错误而导致程序行为出现缺陷的错误。许多竞态条件可能由数据竞争引起,但这并非必要。
考虑以下简单示例,其中x是一个共享变量:
Thread 1 Thread 2
lock(l) lock(l)
x=1 x=2
unlock(l) unlock(l)
在这个例子中,线程1和2对x的写入是受到锁保护的,因此它们始终以运行时获取锁的顺序强制执行。也就是说,写入的原子性不能被破坏;在任何执行过程中,两个写入之间总是存在一种先于关系。我们只是无法事先知道哪个写入发生在另一个之前。
由于锁无法提供固定的排序,因此写入之间没有固定的顺序。如果程序的正确性受到损害,例如在线程2的写入x之后紧跟线程1的写入x时,我们称之为竞争条件,尽管从技术上讲不存在数据竞争。
检测竞争条件比检测数据竞争更加有用,但这也非常难以实现。
构建反向示例也很简单。这篇博客文章还使用一个简单的银行交易示例很好地解释了两者之间的区别。
class Race {
static volatile int i;
static int uniqueInt() { return i++; }
}
uniqueInt
接收到相同的值。数据竞争和竞态条件
在我看来,这绝对是两件不同的事情。
数据竞争
是指多个线程(至少其中一个进行写入)在没有同步的情况下共享相同的内存。
竞态条件
是指未同步的代码块(可能是相同的),它们使用相同的共享资源,在不同的线程上同时运行,其结果是不可预测的。
竞态条件
的示例:
//increment variable
1. read variable
2. change variable
3. write variable
//cache mechanism
1. check if exists in cache and if not
2. load
3. cache
解决方案:
数据竞争
和竞态条件
是原子性问题,它们可以通过同步机制来解决。
数据竞争
- 当对共享变量的写访问将被同步化时竞态条件
- 当代码块作为原子操作运行时