Reputation: 7838
I am reading a post about threading for ruby. And there is a snippet:
q = Queue.new
producer = Thread.new {
c = 0
while true do
q << c
c += 1
puts "#{q.size} in stock"
end
}
consumer1 = Thread.new {
while true
val = q.shift
puts "Consumer - 1: #{val}"
end
}
consumer2 = Thread.new {
while true
val = q.shift
puts "Consumer - 2: #{val}"
end
}
[producer, consumer1, consumer2].each(&:join)
The post says the output will be as:
Thread 2: 25
Thread 1: 22
Thread 2: 26Thread 1: 27
Thread 2: 29
Thread 1: 28
and the cause is:
... a pretty common race condition ...
But I couldn't reproduce that output. And as a java programmer, I don't think the output related to race condition here. I believe it's something related to puts
, but I have no clue to that.
What's going on here?
UPDATE
Thanks for the help from @Damien MATHIEU which explains a lot to a ruby newbie. I found another answer in OS for STDOUT.sync = true
that explains well why we need it and what problems it might cause.
Purpose:
This is done because IO operations are slow and usually it makes more sense to avoid writing every single character immediately to the console.
Possible issues as expected (and what happened in my question):
This behavior leads to problems in certain situations. Imagine you want to build a progress bar (run a loop that outputs single dots between extensive calculations). With buffering the result might be that there isn't any output for a while and then suddenly multiple dots are printed out at once.
Upvotes: 0
Views: 93
Reputation: 32629
That's because puts
doesn't write to STDOUT
right away, but buffers the string and writes in bigger chunks.
You can get ruby to write immediately with the following:
STDOUT.sync = true
which should resolve your ordering issue.
Upvotes: 5