2010-11-16 51 views
5

我碰到的一个竞争条件的例子:红宝石简单的竞争状态的问题

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 

论坛中pararell运行,并有一个机会,当一个线程读取总和的价值,另外一个完成递增,但前者即将完成自己的旧值增加,结果总和不会改变。

但我想知道,为什么当我把'sum = inc(sum)'换成'sum + = 1'时,输出看起来总是正确的。

这是为什么?

是不是因为调用方法的开销比做变量赋值这么大,因此一些线程'不同步'导致输出不正确?

我认为,即使是直线和+ = 1,我仍然能够观察到比赛情况,但只有当我进行了更长的求和循环等时才能观察到比赛情况。

回答

3

是因为调用一个方法的开销比只做一个变量赋值和因此一些线程'不同步'导致输出不正确吗?

是。要验证它,只需增加计数器并运行多个测试。我把它提高到100_000.times和这里的结果:

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

嗯,这似乎不是很好,不是吗?

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