dar*_*ode 3 ruby-on-rails puma ruby-on-rails-5
我在课堂上有这个方法:
class User < ApplicationRecord
...
def answers
@answers ||= HTTParty.get("http://www.example.com/api/users/#{self.id}/answers.json")
end
...
end
Run Code Online (Sandbox Code Playgroud)
由于我使用 Puma 作为网络服务器,我想知道这段代码是否是线程安全的?有人可以确认一下吗?如果可能的话请解释一下为什么这是线程安全的?
这是实例方法中的,不要与类方法混淆。该answers方法位于的实例User上,而不是位于User类本身上。此方法正在缓存 a 实例上的答案User,但只要User使用每个 Web 请求(例如 aUser.find()或User.find_by())实例化该实例,\xe2\x80\x99 就可以了,因为该实例不在线程之间存在。查找控制器中每个 Web 请求的记录是常见做法,因此您很可能会这样做。
如果此方法直接在User类上(例如User.answers),则您需要评估跨线程和 Web 请求维护该缓存值是否安全。
回顾一下,您唯一关心的线程安全是类方法、类变量(使用两个 at 符号的实例变量,例如@@answers)和实例方法(其中实例存在于单个 Web 请求中)。
如果您发现自己需要安全地使用类级变量,则可以使用Thread.current,它本质上是一个可以在其中存储值的每线程哈希(如 {})。例如Thread.current[:foo] = 1就是一个例子。ActiveSupport 在设置时使用此Time.zone。
或者,您可能会发现有时需要一个需要跨线程安全共享的数组,在这种情况下,您\xe2\x80\x99d 需要研究Mutex,这基本上可以让您拥有一个可以锁定和解锁的数组以提供线程安全地在其中读取和写入。例如,Sidekiq gem 使用互斥体来管理工作线程。您锁定互斥锁,以便其他人无法更改它,然后您对其进行写入,然后解锁它。重要的是要注意,如果任何其他线程想要在互斥体锁定时写入互斥体,则它必须等待它解锁(例如,线程只是在另一个线程写入时暂停),因此锁定尽可能短的时间很重要。
| 归档时间: |
|
| 查看次数: |
1409 次 |
| 最近记录: |