Я читаю сообщение о потоках для ruby. И есть фрагмент:
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)
В сообщении говорится, что результат будет такой:
Thread 2: 25
Thread 1: 22
Thread 2: 26Thread 1: 27
Thread 2: 29
Thread 1: 28
и причина:
... довольно распространенное состояние гонки ...
Но я не смог воспроизвести этот вывод. И как программист Java, я не думаю, что результат, связанный с состоянием гонки здесь. Я верю, что это что-то связанное с puts
, но я понятия не имею об этом.
Что здесь происходит?
UPDATE
Спасибо за помощь @Damien MATHIEU, которая многое объясняет рубиновому новичку. Я нашел другой ответ в ОС для STDOUT.sync = true
, который хорошо объясняет, зачем он нам нужен и какие проблемы это может вызвать.
Назначение:
Это сделано потому, что операции ввода-вывода являются медленными, и обычно имеет смысл избегать немедленной записи каждого символа в консоль.
Возможные проблемы, как и ожидалось (и что произошло в моем вопросе):
Такое поведение приводит к проблемам в определенных ситуациях. Представьте, что вы хотите построить индикатор выполнения (запустите цикл, который выводит отдельные точки между обширными вычислениями). С буферизацией может получиться так, что какое-то время не будет никакого вывода, а затем внезапно будут распечатаны сразу несколько точек.