【问题标题】:Ruby/Rails thread safetyRuby/Rails 线程安全
【发布时间】:2010-10-13 10:56:22
【问题描述】:

我不时地使用 Ruby 进行黑客攻击,但我没有用它做任何大的或多线程的事情。我听说 MRI 只支持绿色线程,而 JRuby 通过 JVM 支持本机线程。但是,我在博客和讨论组上偶然发现了 cmets,它们说“Rails 不是线程安全的”或者 Ruby 本身不是线程安全的。例如,有人评论说 require 语句有问题。这听起来有点基本。

我见过很多不能正确处理并发的 Java 应用程序,我不时会做噩梦 :-) 但至少你可以用 Java 编写线程安全的应用程序如果您真的知道自己在做什么(这并不容易)。

这一切听起来都非常令人担忧,有人可以详细说明一下 - 究竟是什么问题以及 Rails 如何在这种情况下设法工作?我可以编写在没有竞争条件和死锁的情况下正常工作的多线程 Ruby 代码吗?它是否可以在 JRuby 和 MRI 之间移植,还是我必须破解 JVM 特定代码才能正确利用 JVM 本机线程?

编辑:

我应该问两个问题,因为人们似乎只回答 rails 线程的东西(这本身很好)和绿色线程与原生线程。我对线程 safety 的核心 Ruby 问题的担忧并没有真正得到解决。在某些情况下,似乎至少有一个(未解决?)issue 需要。

【问题讨论】:

标签: ruby-on-rails ruby multithreading thread-safety jvm-languages


【解决方案1】:

我真的建议你观看 Jim Weirich 在 RubyConf 2008 上的演讲(非常有趣且内容丰富:):

https://www.youtube.com/watch?v=fK-N_VxdW7g

这个也不错:

http://rubyconf2008.confreaks.com/summer-of-code-rails-thread-safety.html

【讨论】:

    【解决方案2】:

    首先,Ruby 1.9(最新的官方版本)now uses native (kernel) threads。早期版本的 Ruby 使用绿色线程。为了简洁地回答您的问题,在 1.9 之前,线程并没有广泛用于大大小小的 Ruby 应用程序,因为它们不是特别安全或可靠。

    这并不特别令人担忧,因为在 2.2 版本之前,Rails 没有尝试线程安全,因此我们通常通过使用多进程、数据库记录锁定和消息队列(如 Starling)来处理异步处理。这通常是扩展 Web 应用程序的一种非常可靠的方法 - 至少与不正确的多线程 Java 应用程序一样可靠 - 并且具有额外的优势,即可以更轻松地将应用程序横向扩展到多个处理器和服务器。

    我不知道你提到的 'require' 问题是否在 1.9 中得到了解决,但我冒昧地冒险,如果你在新线程中动态地需要库,那​​么你就有不止一个可维护性问题。

    如果您想完全避免使用线程,Ruby 1.9 also supports fibers,它采用无共享的并发方法,据我所知,它通常比线程更容易编写和维护。 Performance numbers here.

    【讨论】:

    • 为什么将 anything 与“incorrectly 多线程 Java 应用程序”进行比较很有用?
    • @KirkWoll 我读到回答者暗示“当线程在一种语言中很危险时,在那种语言中可能不值得。”
    【解决方案3】:

    我认为之前的海报很好地涵盖了 Rails 案例,所以我不会费心去讨论那些东西。

    当然可以编写线程化的 Ruby 应用程序。 ruby 线程存在的一些问题是它们是“绿色”的,因为它们是由虚拟机管理的。目前,默认解释器 (MRI) 只有一个真正的系统线程,需要由解释器控制的所有线程共享。

    这样做的缺点是,如果您的计算机具有多个处理器或内核,则您的应用程序中的线程不能在其他内核上运行。这对于运行服务器和高性能应用程序的人来说意义重大。

    至于您的解释器特定代码问题:我不这么认为。 AFAIK 你不需要做任何特别的事情来处理 JRuby/JVM 线程。

    另外:This article 在 Igvita 上可以很好地了解 Ruby 中的并发状态。

    【讨论】:

      【解决方案4】:

      MRI 的正常解决方案是运行多个 Rails 实例,每个实例独立处理请求。由于 MRI 无论如何都不是多线程的,因此您不能在其上运行多个 Rails 实例。这意味着您会受到内存冲击,因为 Rails 会在每个 Ruby 进程中加载​​一次。

      由于 JRuby 支持本地线程,您总是可以在单个 JVM 中运行多个 Rails 实例。但是由于 Rails 是线程安全的,您可以将其减少到一个,这意味着更少的内存使用和更少的 JIT 编译。

      Charles Nutter (JRuby) 有一个nice summary

      【讨论】:

      • 谢谢,Charles Nutter 的总结很棒。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-05
      • 1970-01-01
      • 1970-01-01
      • 2012-04-08
      • 2014-05-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多