Make使线程安全

时间:2015-12-11 16:30:12

标签: ruby multithreading

我有一个多线程程序,可以在数百个地方打印到控制台。不幸的是,而不是

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

如何制作线程安全(即不打印部分线)?

2 个答案:

答案 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