0

这是比赛条件吗?

class A {
   int x; 

   update() {
      x = 5; 
   }

   retrieve() {
      y = x; 
   }
}

如果 update() 和 retrieve() 由两个不同的线程调用而没有持有任何锁,假设在共享变量的两次访问中至少有一次写入,这可以归类为竞争条件。但这真的是运行时的问题吗?

4

1 回答 1

2

没有锁,可能会发生三件事:

  1. y得到x(5) 的新值。
  2. y获取旧值x(很可能为 0)。
  3. 如果写入int不是原子的,则y可以获得任何其他值。

在 Java 中,对 an 的读取int是原子的,因此第三个选项不会发生。不保证其他语言的原子性。

使用锁定,前两个选项也可以发生。

但是,取决于内存模型,还有一个额外的挑战。在 Java 中,如果写入没有同步,则可以任意延迟到下一个同步点(synchronized块结束或对volatile字段的访问)。synchronized类似地,可以从前一个同步点(块的开始或对volatile字段的访问)任意缓存读取。这很容易导致陈旧缓存引起的问题。最终结果是,即使第一个选项应该发生,第二个选项也可能发生。

在 Java 中,始终使用volatile可从其他线程访问的字段,否则您将面临因内存访问重新排序而导致的难以调试的竞争条件。同样的警告也适用于使用类似于 Java 中的内存模型的其他语言 - 您可能需要告诉编译器不要进行这些优化。

于 2012-11-29T12:58:43.343 回答