ruby-on-rails - Ruby 默认是线程安全的吗?

标签 ruby-on-rails ruby multithreading

我在控制台中运行以下代码 10 多次,结果相同,100000

i = 0
1000.times do
Thread.start { 100.times { i += 1 } }
end
i

当我使用多个线程读取和更新 i 时,它不应该给我不同的输出吗?这让我想知道,默认情况下 ruby​​ 实际上是线程安全的吗?如果不是,那为什么我总是看到相同的输出?

附注如果你说,默认情况下它不是线程安全的,那么你能分享一个简单的例子,当我在 Rails 控制台中运行时,它会给我不同的结果吗?

编辑:

换句话说,上面的代码是否同时运行了 1000 个线程?如果是,则结果不应该是 100000 ALWAYS。如果不是,那么如何并发运行多个线程?

如果我添加puts,那么i 的打印顺序将会改变。这意味着线程相互交错,但它们是否同时运行?

我不是在问,如何使这个线程安全。我了解 mutex/locking 和同步/异步进程的概念。因为我理解它们,所以我无法理解这段代码的输出。

最佳答案

没有代码自动是线程安全的,您必须努力使其成为线程安全的。

特别是+=操作实际上是三个操作:read,increment,write。如果这些与其他线程混合在一起,您可能会遇到非常不可预测的行为。

考虑以下两个线程上的一系列事件:

  A       B
-------------
READ
         READ
INCR
         INCR
WRITE
         WRITE

这是最简单的情况,您将有两个增量操作,因为它们都使用相同的原始值,其中一个被取消。

在我的测试中,这不太可能发生在双核系统上,但在四核机器上实际上是一个经常出现的问题,因为许多系统的行为就像两个松散连接的双核系统,每个系统都有自己的缓存。使用 JRuby 时更加明显线程支持要好得多。您的示例代码会为我生成随机答案,范围从 98200 到 99500。

为了使该线程安全,您必须使用Mutex 或使用像Concurrent Ruby 这样的库中的原子增量操作。这将为您提供安全执行此操作的工具。

替代方法是避免在线程之间混合数据或使用类似 Queue 的结构管理通信。如果没有 Mutex,任何两个线程都不应该操作同一个对象。

关于ruby-on-rails - Ruby 默认是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37997976/

相关文章:

ruby-on-rails - 回形针,fog.io和Rackspace

ruby-on-rails - Graphql ruby​​ 中字段和连接的区别?

ruby - 在 Ruby 中增加字符串的一部分

只有 put 和 get 的 Java HashMaps - 可能存在并发问题?

ruby-on-rails - Ruby on Rails 中的单数命名路线

ruby-on-rails - rails : macro style functions

ruby - 如何在安装了 rbenv 的 Mavericks 中运行 boxen?

multithreading - 卡在 UIComponent.popComponentFromEL 的线程

java - 线程交错 - 可以输出什么可能的结果

ruby-on-rails - 在Rails中使用ActiveModel序列化器进行JSON渲染