18

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

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

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

编辑:

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

4

4 回答 4

14

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

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

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

如果您想完全避免使用线程,Ruby 1.9还支持 Fiber,它采用无共享的并发方法,据我所知,通常比线程更容易编写和维护。性能数字在这里

于 2009-03-16T21:23:04.170 回答
6

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

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

这个也不错:

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

于 2009-03-15T20:10:24.837 回答
5

The normal solution for MRI is to run multiple Rails instances, each handling requests independently. Since MRI isn't multithreaded anyway, you can't run multiple Rails instances on top of it. This means you take a memory hit since Rails is loaded once per Ruby process.

Since JRuby supports native threads, you could always run several Rails instances in a single JVM. But with Rails being thread-safe, you can cut it down to one, which means lower memory usage and less JIT compilation.

Charles Nutter (JRuby) has a nice summary.

于 2009-03-15T11:34:03.313 回答
1

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

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

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

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

另外:这篇关于 Igvita 的文章很好地了解了 Ruby 中的并发状态。

于 2009-03-16T04:10:32.217 回答