在没有混淆输出的情况下,在Ruby中从并行操作打印输出的最简单方法是什么?

dan*_*dan 11 ruby multithreading

假设我分叉了一堆线程,并希望将每一个的进度输出打印到STDERR.我怎样才能确保输出保持行原子性,即不会混淆同一输出行中不同线程的输出?

# run this a few times and you'll see the problem
threads = []    
10.times do  
  threads << Thread.new do        
    puts "hello" * 40
  end     
end 
threads.each {|t| t.join}
Run Code Online (Sandbox Code Playgroud)

Way*_*rad 28

puts有一个竞争条件,因为它可以单独写一行换行.您可以在多线程应用程序中使用puts来看到这种噪音:

thread 0thread 1
thread 0thread 2
thread 1
thread 0thread 3
thread 2
thread 1
Run Code Online (Sandbox Code Playgroud)

相反,使用print或printf

print "thread #{i}" + "\n"
print "thread #{i}\n"
printf "thread %d\n", i
Run Code Online (Sandbox Code Playgroud)

或者,因为您要写入STDERR:

$stderr.print "thread #{i}\n"
Run Code Online (Sandbox Code Playgroud)

这是Ruby中的错误吗?如果要将评论作为标准,则不是.这是从MRI 1.8.7到2.2.2的IO.puts的定义:

/*
 *  call-seq:
 *     ios.puts(obj, ...)    => nil
 *
 *  Writes the given objects to <em>ios</em> as with
 *  <code>IO#print</code>. Writes a record separator (typically a
 *  newline) after any that do not already end with a newline sequence.
 *  If called with an array argument, writes each element on a new line.
 *  If called without arguments, outputs a single record separator.
 *
 *     $stdout.puts("this", "is", "a", "test")
 *
 *  <em>produces:</em>
 *
 *     this
 *     is
 *     a
 *     test
 */
Run Code Online (Sandbox Code Playgroud)