Multithreading 具有两个线程的良性数据竞争条件

Multithreading 具有两个线程的良性数据竞争条件,multithreading,race-condition,Multithreading,Race Condition,这是比赛条件吗 class A { int x; update() { x = 5; } retrieve() { y = x; } } 如果update()和retrieve()由两个不同的线程调用,并且没有持有任何锁,那么假设共享变量的两次访问中至少有一次写入,那么这可以归类为竞争条件。但这真的是运行时的问题吗 没有锁,可能会发生三件事: y获取x(5)的新值 y获取x的旧值(很可能是0) 如果写入int的内容不是原子的,则y

这是比赛条件吗

class A {
   int x; 

   update() {
      x = 5; 
   }

   retrieve() {
      y = x; 
   }
}

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

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

  • y
    获取
    x
    (5)的新值
  • y
    获取
    x
    的旧值(很可能是0)
  • 如果写入
    int
    的内容不是原子的,则
    y
    可以获取任何其他值
  • 在Java中,对
    int
    的读取是原子的,因此第三个选项不能出现。不能保证其他语言中的原子性

    通过锁定,前两个选项也可以发生

    不过,根据内存模型,还有一个额外的挑战。在Java中,如果一个写操作没有同步,它可以被任意延迟到下一个同步点(一个
    synchronized
    块的末尾或一个
    volatile
    字段的访问)。类似地,可以从上一个同步点(同步的
    块的开始或对
    volatile
    字段的访问)任意缓存读取。这很容易导致过时缓存引起的问题。最终的结果是,第二种选择可能发生,即使第一种选择应该发生


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

    什么语言?或者说这是一个语言不可知的问题吗?把这样一个粗俗的种族称为“良性”就像在C++中调用一只老虎一样大,不稳定不保证任何同步或记忆障碍。它所做的只是防止某些类型的优化。我听说VC++会无缘无故地创建一个内存屏障,但这不是标准的。@JiveDadson那么它就不是Java的
    volatile
    的等价物了。重写。@JiveDadson如果
    volatile
    关键字没有剪切它,那么我不知道会发生什么。Microsoft编译器可以保证这一点: