Regexp.last_match线程安全吗?

Fed*_*ico 18 ruby

这是我正在看的代码:

def method_missing(id, *args)
    return self.find(Regexp.last_match(1),  args[0]) if id.id2name =~ /find_by_(.+)/
    raise NoMethodError
end
Run Code Online (Sandbox Code Playgroud)

如果我有多个线程调用会发生什么Regexp.last_match

如果我有多个线程使用该method_missing方法调用该对象会发生什么?

Ale*_*x D 24

Ruby 1.9.2平台文档声明调用Regexp.last_match等同于读取特殊的$~全局变量.

从"Ruby编程语言",第318页:"重要的是要记住$〜和从它派生的变量都是线程本地的和方法本地的."

因此Regexp.last_match 线程安全的.至于你使用的其他方法method_missing,我相信它们也是线程安全的.(如果有人不同,请编辑这篇文章.)


Tod*_*obs 6

TL; DR

是的,Regexp特殊全局变量是线程安全的,因为它们不是真正的全局变量。尽管这些变量的名称中都有“ global”一词,但文档中说:

这些全局变量是线程局部变量和方法局部变量。

线程数

您可以在irb或prep 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"]
Run Code Online (Sandbox Code Playgroud)

方法

当在方法中使用时,这些特殊变量甚至不是真正的全局变量。考虑以下:

def foo
  'foo'.match /(foo)/
  p $1
end 

[foo, $1]
#=> ["foo", nil]
Run Code Online (Sandbox Code Playgroud)

结论

换句话说,由于前缀,Regexp特殊变量看起来像是真正的全局变量$,但不会在封闭的线程或方法之外持续存在。您必须在多大程度上证明将它们称为“全局变量”是合理的,您必须与语言设计师联系,或者提交有关您是否强烈认为它具有误导性的错误。