gpt4 book ai didi

ruby-on-rails - Rails 中的类实例变量应该在互斥体中设置吗?

转载 作者:数据小太阳 更新时间:2023-10-29 07:10:49 25 4
gpt4 key购买 nike

假设我的 Rails 项目中有一个设置实例变量的 Ruby 类。

class Something
def self.objects
@objects ||= begin
# some logic that builds an array, which is ultimately stored in @objects
end
end
end

是否可以多次设置@objects?是否有可能在一个请求期间,在上面的 begin/end 之间执行代码时,可以在第二个请求期间调用此方法?我想这实际上归结为 Rails 服务器实例如何 fork 的问题。

我应该改用 Mutex 还是线程同步?例如:

class Something
def self.objects
return @objects if @objects

Thread.exclusive do
@objects ||= begin
# some logic that builds an array, which is ultimately stored in @objects
end
end
end
end

最佳答案

即使在 MRI 中,也可以(并且希望)以多线程模式运行 Rails。这可以通过更改 production.rb 中的一行来完成。

config.threadsafe!

在 MRI 中,两个线程不能同时运行代码,但上下文切换可以随时发生。在 Rubinius 和 JRuby 中,线程可以同时运行代码。

让我们看看您显示的代码:

class Something
def self.objects
@objects ||= begin
# some logic that builds an array, which is ultimately stored in @objects
end
end
end

||= 代码被扩展为如下内容:

class Something
def self.objects
@objects || (@objects = begin
# some logic that builds an array, which is ultimately stored in @objects
end)
end
end

这意味着该过程实际上有两个步骤:

  1. 查找@objects
  2. 如果@objects 为假,将@objects 设置为begin/end 表达式的结果

上下文可能会在这些步骤之间切换。上下文当然有可能在步骤 2 的中间切换。这意味着您最终可能会多次运行该 block 而不是一次。在 MRI 中,这可能是可以接受的,但在表达式周围锁定一个互斥量是非常直接的,所以就这样做吧。

class Something
MUTEX = Mutex.new

def self.objects
MUTEX.synchronize do
@objects ||= begin
# some logic that builds an array, which is ultimately stored in @objects
end
end
end
end

关于ruby-on-rails - Rails 中的类实例变量应该在互斥体中设置吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10386590/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com