Ruby on rails Rails类方法是线程安全的吗?

Ruby on rails Rails类方法是线程安全的吗?,ruby-on-rails,ruby-on-rails-5,puma,Ruby On Rails,Ruby On Rails 5,Puma,我在一个类中使用了这个方法: class User < ApplicationRecord ... def answers @answers ||= HTTParty.get("http://www.example.com/api/users/#{self.id}/answers.json") end ... end class用户

我在一个类中使用了这个方法:

class User < ApplicationRecord
  ...

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

  ...
end
class用户

由于我使用Puma作为web服务器,我想知道这段代码是否是线程安全的?有人能确认一下吗?如果可能的话,解释一下为什么这是线程安全的吗?

这在实例方法中,不要与类方法混淆。
answers
方法在
User
的实例上,而不是在
User
类本身上。此方法正在缓存
用户
实例上的答案,但只要此
用户
实例与每个web请求一起实例化(例如
用户.find()
用户.find_by()
),就可以了,因为该实例不在线程之间。通常的做法是在控制器中查找每个web请求的记录,因此您可能会这样做

如果此方法直接在
User
类上(例如
User.answers
),则需要评估跨线程和web请求维护缓存值是否安全

综上所述,您对线程安全唯一关心的是类方法、类变量(使用两个at符号的实例变量,如
@@answers
),以及实例通过单个web请求生存的实例方法

如果您发现自己需要安全地使用类级变量,可以使用
Thread.current
,它本质上是一个可以存储值的每线程散列(如{})。例如
Thread.current[:foo]=1
就是一个例子。ActiveSupport在设置时区时使用此选项


或者,您可能会发现需要在线程之间安全共享单个数组的情况,在这种情况下,您需要查看
互斥锁
,它基本上让您拥有一个可以锁定和解锁的数组,以便线程能够安全地读写该数组。例如,Sidekiq gem使用互斥来管理工人。锁定互斥锁,这样其他人就无法更改它,然后写入互斥锁,然后解锁互斥锁。需要注意的是,如果任何其他线程希望在锁定互斥锁时写入互斥锁,那么它必须等待互斥锁解锁(比如,当其他线程写入时线程只是暂停),因此尽可能短的锁定非常重要

基于我对
puma
的有限了解,单独的puma线程不共享相同的
user
实例。因此,我们将在每个puma线程中分别提出GET请求,谢谢您的回答。如何验证实例方法是否存在于单个web请求之后?@Crashalot对于要在多个web请求中使用的对象实例(可能不安全),您需要使用类变量、类级别实例变量、常量或线程局部变量。如果你只是发布一个带有相关代码的问题,可能会更容易。