使puts方法线程安全

5
我是一个多线程程序,需要在数百个位置打印到控制台。不幸的是,输出并不总是按照期望的顺序出现,这使得很难跟踪哪个输出对应哪个线程。我该怎么办?
Line 2
Line 1
Line 3

我明白了

Line2Line1

Line3

我想要使puts具备线程安全性。


在Python中(我不认为它有这个问题,但假设它确实存在),我会这样做:

old_print = print

print_mutex = threading.Lock()

def print(*args, **kwargs):
    print_mutex.acquire()
    try:
        old_print(*args, **kwargs)
    finally:
        print_mutex.release()

我正在尝试使用Ruby进行此操作,

old_puts = puts

puts_mutex = Mutex.new

def puts(*args)
    puts_mutex.synchronize {
        old_puts(*args)
    }

但是这个方法不起作用:"undefined method old_puts"


如何实现线程安全(即不打印部分行)?


4
提示:当你执行 old_puts = puts 时,隐式地执行了 old_puts = puts() - Damiano Stoffie
2个回答

6
alias old_puts puts

更现代的方式:
module MyKernel
  PutsMutex = Mutex.new
  def puts(*)
    PutsMutex.synchronize{super}
  end
end

module Kernel
  prepend MyKernel
end

1
这种行为的原因在于puts内部调用底层的write函数两次——一次写入实际值,一次写入换行符。(在Ruby's puts is not atomic中有解释)。
以下是一种hack方法,可使puts仅调用一次write:将\n添加到要写入的字符串末尾。以下是我代码中的示例:
# Threadsafe `puts` that outputs text and newline atomically
def safe_puts(msg)
    puts msg + "\n"
end

puts 内部会检查被写入的对象是否以换行符结尾,只有在不是这种情况时才会再次调用 write。由于我们已经改变了输入以以换行符结尾,puts 最终只会调用一次 write


这是否意味着,如果您使用print而不是puts,并将换行符作为传递给print的字符串的一部分,那么您就不需要safe_puts了? - Keith Bennett
另外,对于我来说,我真正需要的是一种将多行内容打印在一个原子操作中的方法。我想我需要做和之前建议的一样的事情,就是自己构建多行字符串,然后将其传递给print函数? - Keith Bennett
是的,没错 :) - rohitpaulk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接