这是我正在查看的代码:
def method_missing(id, *args)
return self.find(Regexp.last_match(1), args[0]) if id.id2name =~ /find_by_(.+)/
raise NoMethodError
end
如果我有多个线程正在调用Regexp.last_match
会怎样?
如果我有多个线程使用method_missing
方法调用对象会怎样?
答案 0 :(得分:24)
Ruby 1.9.2平台文档声明调用Regexp.last_match
等同于读取特殊的$~
全局变量。
从“Ruby编程语言”,第318页:“重要的是要记住$〜和从它派生的变量都是线程本地的和方法本地的。”
所以Regexp.last_match
是线程安全的。至于您在method_missing
中使用的其他方法,我相信它们也是线程安全的。 (如果有人不同,请编辑这篇文章。)
答案 1 :(得分:6)
是的,Regexp special global variables是线程安全的,因为它们不是真正的全局变量。尽管变量在名称中包含“global”一词,但文档说:
这些全局变量是线程局部变量和方法局部变量。
你可以用irb或pry REPL证明这一点。例如,要在线程内测试变量的范围:
# Ensure $~ and friends are nil in case this isn't a fresh REPL.
''.match /foo/
# Make this variable available inside the thread block.
thread_match = nil
Thread.new do
'foo'.match /(foo)/
thread_match = "In thread: #{$1.inspect}"
end
[thread_match, "Global value: #{$1.inspect}"]
#=> ["In thread: \"foo\"", "Global value: nil"]
在方法中使用时,这些特殊变量甚至不是真正的全局变量。请考虑以下事项:
def foo
'foo'.match /(foo)/
p $1
end
[foo, $1]
#=> ["foo", nil]
换句话说,由于$
前缀,Regexp特殊变量看起来像一样真正的全局变量,但是不要在封闭线程或方法之外保留。在多大程度上证明称他们为“全局”是你必须要接受语言设计师的事情,或者提出一个错误,如果你强烈认为这是误导性的。
答案 2 :(得分:0)
这似乎表明使用@Todd A. Jacobs的答案中的方法不是线程安全的。
➜ ~ irb
irb(main):001:0> thread_match = nil
=> nil
irb(main):002:0> Thread.new do
irb(main):003:1* /([[:alpha:]])*/.match('BF92')
irb(main):004:1> thread_match = "In thread: #{$1.inspect}"
irb(main):005:1> end
=> #<Thread:0x00007f8cfc971090@(irb):2 run>
irb(main):006:0> thread_match
=> "In thread: \"F\""
irb(main):007:0>