Метод класса Rails является потокобезопасным? - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть этот метод в классе:

class User < ApplicationRecord
  ...

  def answers
    @answers ||= HTTParty.get("http://www.example.com/api/users/#{self.id}/answers.json")
  end

  ...
end

Поскольку я использую Puma в качестве веб-сервера, мне интересно, является ли этот код потокобезопасным?Может кто-нибудь подтвердить это и, если возможно, объяснить, почему это потокобезопасно?

1 Ответ

0 голосов
/ 18 декабря 2018

Это в методе экземпляра, не путать с методом класса.answers метод для экземпляра из User, а не для самого класса User.Этот метод кэширует ответы в экземпляре User, но пока этот экземпляр User создается при каждом веб-запросе (например, User.find() или User.find_by()), все в порядке, потому чтоЭкземпляр не живет между потоками.Обычной практикой является поиск записей каждого веб-запроса в контроллере, так что вы, вероятно, делаете это.

Если этот метод был непосредственно для класса User (например, User.answers), то вы 'Мне нужно оценить, безопасно ли сохранять это кэшированное значение в потоках и веб-запросах.

Напомним, что единственная забота о безопасности потоков - это методы класса, переменные класса (переменные экземпляра, которые используют два в знаке)такие как @@answers), и методы экземпляра, где экземпляр живет после одного веб-запроса.

Если вам когда-нибудь понадобится безопасно использовать переменную уровня класса, вы можете использовать Thread.current, которыйпо сути является хешем для каждого потока (например, {}), в котором вы можете хранить значения. Например, Thread.current[:foo] = 1 будет примером.ActiveSupport использует это при настройке Time.zone.

В качестве альтернативы вы можете найти моменты, когда вам нужен отдельный массив, который вам нужно безопасно разделить между потоками, и в этом случае вам нужно будет просмотреть Mutex, чтов основном позволяет вам иметь массив, который вы блокируете и разблокируете, чтобы обеспечить потокам безопасный доступ к чтению и записи в нем.Например, в Sidekiq для управления рабочими используется Mutex.Вы блокируете Mutex, чтобы никто другой не мог его изменить, затем пишете в него, а затем разблокируете его.Важно отметить, что если какой-либо другой поток захочет записать в Mutex, пока он заблокирован, ему придется подождать, пока он разблокируется (например, поток просто делает паузу, пока другой поток пишет), поэтому важно заблокировать какКороче как можно.

...