在Ruby中解释这种竞争条件

时间:2019-02-17 09:42:09

标签: ruby multithreading

四个线程分别循环1000万次。在每个循环中,如果列表为空,他们会推送一个数字,否则会从列表中弹出一个数字。

list = []

threads = []

4.times do |i|
  threads << Thread.new do
    1e7.to_i.times do |i|
      if list.empty?
        list << i
      else
        list.pop
      end
    end
  end
end

threads.each(&:join)
p list

由于循环执行偶数次,所以我希望所有线程执行完后,列表为空。

但是,有时列表中包含数字9999999。

由于GIL,我认为MRI Ruby中的Array是线程安全的。

尽管有GIL,比赛条件如何发生?

1 个答案:

答案 0 :(得分:2)

一次仅执行一个线程并不意味着一个线程总是在有用的行处停止,例如在下一个线程获得执行时间之前在一个块的末尾。

在您的示例中,一个线程有可能读取并评估list.empty?,然后必须等待另一个线程。另一个线程也读取并求值list.empty?,并获得与第一个线程相同的结果。之后,两个线程将执行if条件的相同分支,因为它们看到的状态相同。