gpt4 book ai didi

ruby - 为什么a + = 1是Ruby中的线程安全操作?

转载 作者:行者123 更新时间:2023-12-03 13:14:16 25 4
gpt4 key购买 nike

代码段:

a = 0
Array.new(50){
Thread.new {
500_000.times { a += 1 }
}
}.each(&:join)
p "a: #{a}"

结果: a = 25_000_000

据我了解,(MRI)Ruby使用GIL,因此只有一个 ruby 线程可以获取CPU,但是当发生线程切换时,将存储 ruby 线程的一些数据以供以后恢复线程。因此,从理论上讲, a += 1可能不是线程安全的。

但是上面的结果证明我是错的。 Ruby是否使 a+=1原子化?如果为true,则可以认为哪些操作是线程安全的?

最佳答案

既不是原子也不是线程安全的

在您的示例中,表观的一致性在很大程度上是由于全局解释器锁定,但也部分是由于Ruby引擎和代码序列(理论上)异步线程的方式所致。您将获得一致的结果,因为每个线程中的每个循环都只是在递增a的当前值,而不是块局部变量或线程局部变量。在YARV虚拟机上使用线程时,一次仅一个线程正在检查或设置a的当前值,但是我真的不能说这是一个原子操作。这只是引擎在线程之间缺乏实时并发以及Ruby虚拟机的基础实现的副产品。

如果您担心在Ruby中保留线程安全性而不依赖于恰好看起来一致的特有行为,请考虑使用诸如concurrent-ruby之类的线程安全库。否则,您可能依赖于Ruby引擎或Ruby版本无法保证的行为。

例如,在JRuby中有三个连续的代码运行(确实有并发线程),每次运行通常会产生不同的结果。例如:

  • #=> "a: 3353241"
  • #=> "a: 3088145"
  • #=> "a: 2642263"
  • 关于ruby - 为什么a + = 1是Ruby中的线程安全操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62233487/

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