在Rails操作中使用Thread.new

时间:2019-05-09 22:36:11

标签: ruby-on-rails ruby parallel-processing

使用多进程应用服务器并在控制器操作中运行Thread.new(产生多个线程)时,是否达到并行性?还是GIL阻止了这种情况的发生?

2 个答案:

答案 0 :(得分:3)

全局解释器锁(GIL)阻止在任何给定时间运行多个Ruby线程,其最终结果是将Ruby仅限制为一个内核。除此之外,它们是实际的线程。

如果需要真正的并发性,则需要运行没有GIL的Ruby,例如JRuby。

话虽这么说,Ruby中的线程对于许多不需要固定CPU内核的操作来说是很好的选择。如果您是,则应该通过ActiveJob为这些操作创建后台作业。如有必要,它们可以在不同系统上的一个或多个进程中运行。

答案 1 :(得分:2)

@tadman的答案是完全正确的,我只想在第3段上扩大一点。

什么时候在MRI Ruby中使用线程是一件好事?通常,如果您受IO操作的约束。因此,如果您有一个Rails操作,其中有许多数据库查询和/或http请求,则可以在线程中进行查询,将请求安全放在线程局部变量中,将它们联接在一起,然后处理线程局部变量。这样,您将获得明显的性能改进。

这可能看起来像这样:

threads << Thread.new do
  ActiveRecord::Base.connection_pool.with_connection do
  t = Thread.current
  t[:variable_name] = Model.find_by(col: data)
  end
end
joined_threads = threads.map &:join
joined_threads.each do |t|
  t.keys.each do |key|
    k = key.to_s.downcase
    next if k.start_with?("active") || k.start_with?("__")
    instance_variable_set "@#{key}", t[key]
  end
end