{puts}中是否存在竞争条件?

时间:2019-03-27 10:31:33

标签: ruby multithreading

我正在阅读post的关于红宝石穿线的信息。有一个摘要:

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有关,但我对此一无所知。

这是怎么回事?


更新

感谢@Damien MATHIEU的帮助,这对红宝石新手有很多帮助。我发现了另一个answer in OS for STDOUT.sync = true,很好地解释了我们为什么需要它以及它可能引起什么问题。

目的:

  

之所以这样做,是因为IO操作速度很慢,通常避免直接将每个字符写入控制台更有意义。

可能出现的问题(以及我的问题发生了什么):

  

在某些情况下,此行为会导致问题。假设您要构建一个进度条(运行一个循环,在大量计算之间输出单个点)。使用缓冲后,结果可能是一段时间没有任何输出,然后突然一次打印出多个点。

1 个答案:

答案 0 :(得分:5)

这是因为puts不会立即写入STDOUT,而是会缓冲字符串并以更大的块写入。

您可以使用以下命令立即获得ruby的书写:

STDOUT.sync = true

这应该可以解决您的订购问题。