开发者

ruby simple race condition question

I came across this example of a 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

thread开发者_开发技巧s.each(&:join)
p sum

Threads run in pararell and there's a chance that while one thread reads sum's value, another one completes incrementing it, but the former is about to finish its own incrementing with the old value, and as a result sum won't change.

But I was wondering, why when I replace the line 'sum = inc(sum)' to 'sum += 1', the output appears to be always correct.

Why is that?

Is it because the overhead of calling a method is so huge compared to just doing a variable assignment and thus some threads 'get out of sync' causing the output to be incorrect?

I assume, that even with a straight sum += 1 I would still be able to observe a race condition, but only if I had been doing a much longer summing loop, etc.?


Is it because the overhead of calling a method is so huge compared to just doing a variable assignment and thus some threads 'get out of sync' causing the output to be incorrect?

Yes. To verify it, just increase your counter and run several tests. I increased it to 100_000.times and here are the results:

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

Well, it doesn't seem that nice, does it?

So, yes, increment is not atomic in Ruby (and I doubt that there's a lot of languages where it is). But there are helper classes to implement such behavior; for example, this one.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜