Метод класса Rails является потокобезопасным?

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

class User < ApplicationRecord
  ...

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

  ...
end

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

Исходя из моих ограниченных знаний о puma, отдельные потоки puma не используют один и тот же экземпляр user. Следовательно, будет выполняться отдельный запрос GET в каждом потоке puma

Lenin Raj Rajasekaran 18.12.2018 02:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
812
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

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

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

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

Спасибо за ответ. Как вы проверяете, действует ли метод экземпляра после одного веб-запроса?

Crashalot 19.06.2020 08:59

@Crashalot Чтобы экземпляр объекта можно было использовать в нескольких веб-запросах (что потенциально небезопасно), вам необходимо использовать переменную класса, переменную экземпляра уровня класса, константу или локальную переменную потока. Вероятно, было бы проще, если бы вы просто разместили вопрос с соответствующим кодом.

Nate 20.06.2020 05:44

Другие вопросы по теме