qqr*_*ryq 5 ruby multithreading race-condition
我遇到了一个竞争条件的例子:
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
Run Code Online (Sandbox Code Playgroud)
线程以pararell运行,并且有可能当一个线程读取sum的值时,另一个线程完成递增它,但前者即将用旧值完成自己的递增,因此sum将不会改变.
但我想知道,为什么当我将'sum = inc(sum)'行替换为'sum + = 1'时,输出似乎总是正确的.
这是为什么?
是因为调用方法的开销与仅执行变量赋值相比是如此巨大,因此一些线程"失去同步"导致输出不正确?
我假设,即使有一个直的+ + 1,我仍然可以观察到一个竞争条件,但只有当我做了更长的求和循环等时?
是否是因为与仅进行变量赋值相比,调用方法的开销如此之大,因此某些线程“不同步”导致输出不正确?
是的。要验证它,只需增加计数器并运行几次测试即可。我将其增加到100_000.times以下是结果:
$ seq 5 | xargs -L 1 ruby a.rb 100000
451167
472581
464413
442191
454204
Run Code Online (Sandbox Code Playgroud)
嗯,看起来不太好,不是吗?
所以,是的,增量在 Ruby 中不是原子的(我怀疑有很多语言都是原子的)。但是有一些辅助类可以实现这种行为;例如这个。
| 归档时间: |
|
| 查看次数: |
595 次 |
| 最近记录: |