gpt4 book ai didi

ruby - 使用 MRI 生成竞争条件

转载 作者:数据小太阳 更新时间:2023-10-29 07:07:31 24 4
gpt4 key购买 nike

我想知道使用 MRI ruby​​(2.0.0) 和一些全局变量来创建竞争条件是否容易,但事实证明这并不容易。看起来它应该在某个时候失败,但它没有,我已经运行了 10 分钟。这是我一直在努力实现的代码:

def inc(*)
a = $x
a += 1
a *= 3000
a /= 3000
$x = a
end

THREADS = 10
COUNT = 5000

loop do
$x = 1
THREADS.times.map do Thread.new { COUNT.times(&method(:inc)) } end.each(&:join)

break puts "woo hoo!" if $x != THREADS * COUNT + 1
end

puts $x

为什么我无法生成(或检测到)预期的竞争条件,并在 Ruby MRI 2.0.0 中获得输出 woo hoo!

最佳答案

您的示例确实(几乎立即)在 1.8.7 中工作。

以下变体适用于 1.9.3+:

def inc
a = $x + 1
# Just one microsecond
sleep 0.000001
$x = a
end

THREADS = 10
COUNT = 50

loop do
$x = 1
THREADS.times.map { Thread.new { COUNT.times { inc } } }.each(&:join)
break puts "woo hoo!" if $x != THREADS * COUNT + 1
puts "No problem this time."
end

puts $x

sleep 命令强烈提示解释器它可以安排另一个线程,所以这并不奇怪。

请注意,如果您将 sleep 替换为需要同样长或更长的时间,例如b = a; 500.times { b *= 100 } ,那么上面的代码中没有检测到竞争条件。但是使用 b = a; 更进一步2500.times { b *= 100 } ,或者将 COUNT 从 50 增加到 500,竞争条件更可靠地被触发。

Ruby 1.9.3 之后的线程调度(当然包括 2.0.0)似乎比 1.8.7 分配了更大块的 CPU 时间。在简单代码中切换线程的机会可能很少,除非涉及某种 I/O 等待。

甚至有可能 OP 中的线程(每个线程只执行几千次计算)本质上是串联发生的 - 尽管增加 COUNT 全局以避免这种情况仍然没有触发额外的竞争条件。

通常,MRI Ruby 不会在其 C 实现中发生的原子进程期间(例如,在 Fixnum 乘法或除法期间)在线程之间切换上下文。这意味着线程上下文切换的唯一机会是在每行代码“之间”,其中所有方法都是对 Ruby 内部的调用而无需等待 I/O。在最初的例子中,只有 4 个这样的转瞬即逝的机会,似乎在 MRI 1.9.3+ 中这根本不是很多(事实上,请参阅下面的更新,这些机会可能已被删除由 ruby )

当涉及到 I/O 等待或 sleep 时,它实际上变得更加复杂,因为 Ruby MRI (1.9+) 将允许在多核 CPU 上进行一些真正的并行处理。虽然这不是线程竞争条件的直接原因,但更有可能导致它们,因为 Ruby 通常会同时进行线程上下文切换以利用并行性。

在研究这个粗略的答案时,我发现了一个有趣的链接:Nobody understands the GIL (第 2 部分已链接,与此问题更相关)


更新:我怀疑解释器正在优化一些潜在的线程切换点在 Ruby 源代码中。从我的代码的 sleep 版本开始,然后设置:

COUNT   = 500000

inc 的以下变体似乎没有影响 $x 的竞争条件:

def inc
a = $x + 1
b = 0
b += 1
$x = a
end

但是,这些微小的变化都会触发竞争条件:

def inc
a = $x + 1
b = 0
b = b.send( :+, 1 )
$x = a
end

def inc
a = $x + 1
b = 0
b += '1'.to_i
$x = a
end

我的解释是 Ruby 解析器优化了 b += 1 以移除一些方法调度的开销。优化的步骤之一可能包括检查是否可能切换到等待线程。

如果是这样,那么问题中的代码可能永远没有机会在 inc 方法内切换线程,因为它里面的所有操作都可以优化以同样的方式。

关于ruby - 使用 MRI 生成竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18574254/

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