我有一个多线程程序,可以在数百个地方打印到控制台。不幸的是,而不是
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)
}
但这不起作用:“未定义的方法old_puts
”
如何制作线程安全(即不打印部分线)?
答案 0 :(得分:6)
alias old_puts puts
或更现代的方式:
module MyKernel
PutsMutex = Mutex.new
def puts(*)
PutsMutex.synchronize{super}
end
end
module Kernel
prepend MyKernel
end
答案 1 :(得分:1)
这种行为的原因是puts
内部调用基础write
函数两次 - 一次用于写入实际值,一次用于写入换行。 (在Ruby's puts is not atomic中解释)
这是让puts
只调用write
一次的黑客攻击:将\n
附加到您正在编写的字符串中。以下是我的代码中的内容:
# Threadsafe `puts` that outputs text and newline atomically
def safe_puts(msg)
puts msg + "\n"
end
puts
在内部检查正在写入的对象是否在末尾有换行符,如果不是,则仅再次调用write
。由于我们已将输入更改为以换行符结尾,因此puts
最终只能调用write
。