【问题标题】:ruby simple race condition question红宝石简单的比赛条件问题
【发布时间】:2011-05-10 19:17:22
【问题描述】:

我遇到了这个竞争条件的例子:

def inc(n)
  n + 1
end

sum = 0

threads = (1..10).map do
  Thread.new do
    10_000.times do
      sum = inc(sum)
    end
  end
end

threads.each(&:join)
p sum

线程以并行方式运行,并且有可能当一个线程读取 sum 的值时,另一个线程完成递增它,但前者即将完成它自己与旧值的递增,因此 sum 不会改变。

但我想知道,为什么当我将“sum = inc(sum)”行替换为“sum += 1”时,输出似乎总是正确的。

为什么会这样?

是不是因为调用方法的开销与仅执行变量赋值相比如此巨大,因此某些线程“不同步”导致输出不正确?

我假设,即使直接求和 += 1,我仍然能够观察到竞态条件,但前提是我进行了更长的求和循环等?

【问题讨论】:

    标签: ruby multithreading race-condition


    【解决方案1】:

    是不是因为调用方法的开销与仅执行变量赋值相比如此巨大,因此某些线程“不同步”导致输出不正确?

    是的。要验证它,只需增加你的计数器并运行几个测试。我将其增加到100_000.times,结果如下:

    $ seq 5 | xargs -L 1 ruby a.rb 100000
    451167
    472581
    464413
    442191
    454204
    

    嗯,看起来不太好,是吗?

    所以,是的,增量在 Ruby 中不是原子的(我怀疑它存在的语言很多)。但是有帮助类来实现这种行为;例如,this one

    【讨论】:

      猜你喜欢
      • 2011-05-24
      • 1970-01-01
      • 2013-01-18
      • 2016-03-23
      • 2012-08-30
      • 1970-01-01
      • 2011-01-09
      • 2016-08-07
      • 2016-05-16
      相关资源
      最近更新 更多