Подтвердить что ты не робот

Является ли Regexp.last_match потоком безопасным?

Это код, на который я смотрю:

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?

4b9b3361

Ответ 1

В документах платформы Ruby 1.9.2 указано, что вызов Regexp.last_match эквивалентен чтению специальной переменной $~.

Из "Язык программирования Ruby", стр. 318: "важно помнить, что $~ и полученные из него переменные являются локальными и локальными методами."

So Regexp.last_match является потокобезопасным. Что касается других методов, которые вы используете в method_missing, я считаю, что они также потокобезопасны. (Если кто-то знает по-другому, отредактируйте этот пост.)

Ответ 2

TL; DR

Да, специальные глобальные переменные Regexp являются поточно- ориентированными, потому что они не являются глобальными. Несмотря на то, что переменные имеют в названии слово "глобальный", в документации говорится:

Эти глобальные переменные являются локальными переменными потока и переменными метода.

Потоки

Вы можете доказать это себе в 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 выглядят как настоящие глобальные переменные из- $ префикса $, но не сохраняются вне окружающего потока или метода. В какой степени это оправдывает называть их "глобальными" вообще - это то, с чем вам придется столкнуться с разработчиками языка или сообщить об ошибке, если вы твердо уверены, что она вводит в заблуждение.

Ответ 3

Казалось бы, это говорит о том, что использование потока в ответе @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:[email protected](irb):2 run>
irb(main):006:0> thread_match
=> "In thread: \"F\""
irb(main):007:0>