Наличие нескольких процессов, записывающих в один и тот же файл, обычно не очень хорошая идея. В большинстве случаев, если вы точно не знаете, что делаете, результат будет непредсказуемым, как вы только что продемонстрировали на своем примере.
Причина, по которой вы получаете странный результат, заключается в том, что объект Ruby IO имеет собственный внутренний буфер . Этот буфер хранится в памяти и НЕ гарантированно записывается на диск при вызове <<
.
. Здесь происходит то, что строка hello from parent
записывается только во внутренний буфер, а не в диск. Затем, когда вы позвоните fork
, вы будете копировать этот буфер в дочерний. Затем дочерний элемент добавит hello from child
в буфер, и только тогда буфер будет записан на диск.
В результате все дочерние элементы будут записывать hello from parent
, в дополнение к записи hello from child
, поскольку это то, что будет содержать внутренний буфер памяти к тому времени, когда Ruby решит записать буфер на диск.
Чтобы обойти эту проблему, вы можете вызвать IO.flush
перед разветвлением, чтобы убедиться, что буфер памяти пуст и сбрасывается на диск перед разветвлением. Это гарантирует, что буфер у дочернего элемента пуст, и теперь вы получите ожидаемый результат:
CSV.open(...) do |target_file|
target_file << ...
target_file.flush # <-- Make sure the internal buffer is flushed to disk before forking
a.each do |num|
... Process.fork ...
end
end
...