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.
精彩评论