- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我想知道使用 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/
我一定遗漏了一些东西,但我用 Ruby 编写的每个应用程序似乎都在泄漏一些内存。我使用 Ruby MRI 2.3,但我看到其他版本的行为相同。 每当我编写一个在循环中执行某些操作的测试应用程序时,它都
我得到了一个数据集,其中包含大脑 MRI 扫描的图像大小。有了这些图像,我将移除头骨,只留下大脑。是否有任何好的分割技术可以用于这些类型的图像? 最佳答案 看起来头骨始终位于图像的外侧,并且始终与大脑
是否可以在一个 VTK 或什至 QT 窗口中并排显示所有 MRI 图像?到目前为止,我已经从矩阵 vector 中的重建中获得了所有 MRI 切片,我可以滚动它们(用 C++ 编写)。我不知道我是否可
我从事 MRI 方面的工作。问题是图像并不总是居中。此外,患者 body 周围常有黑带。 我希望能够像这样去除黑色边框并使患者的 body 居中: 我已经尝试通过读取像素表来确定患者 body 的边缘
是语言翻译吗?还是字节码解释器/JIT 编译器?我在哪里可以了解有关实现的更多信息(除了浏览源代码)? 最佳答案 这是一个名为 YARV 的字节码解释器,由 Sasada Koichi 编写。 下面是
最近的一个问题“What happened with Ruby 1.9.2?”让我想知道 MRI Ruby 的版本号是什么意思。 MRI Ruby 使用的方案不同于 semver.org . MRI
我关于 SO 的第一个问题,但我已经潜伏了很长时间,所以如果我违反了任何规则或发布了垃圾问题,你必须原谅我。 我试图更好地理解线程,因此我决定测试 MRI 并了解它的总体性能。 给定以下代码(和输出)
我想知道使用 MRI ruby(2.0.0) 和一些全局变量来创建竞争条件是否容易,但事实证明这并不容易。看起来它应该在某个时候失败,但它没有,我已经运行了 10 分钟。这是我一直在努力实现的代码
今天我试图向一位同事解释 ||= 在 MRI 中不是线程安全的。我想我应该看一下 Ruby 源代码,看看我是否可以指出 Ruby 调度程序可以切换线程上下文的位置,但是我在浏览代码时遇到了问题。我希望
有谁知道 pdp8 硬件(以及它是否因型号而异)如何处理页面边界上的 mri 指令。例如,如果您的指令位于地址 0177,则程序计数器用于读取该指令,然后实质上递增。如果指定地址的当前页是要使用页0、
我需要图像分割方面的帮助。我有脑部肿瘤的 MRI 图像。我需要从 MRI 中移除颅骨(头骨),然后仅分割肿瘤对象。我怎么能在 python 中做到这一点?与图像处理。我试过制作轮廓,但我不知道如何找到
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 7 年前。 Improve this qu
我有一个 Ruby web 服务,我最近检查了使用 JRuby(9.1.17.0,OpenJDK 1.8)是否会相对于当前使用的 MRI (2.5.0) 提高性能。我预计可能会是这种情况,因为性能瓶颈
我正在编写一个应用程序来计算医疗记录。该应用程序将计算页数并将其除以 20,以确定为客户打印记录所需的胶片数量。我有一个壁橱案例,当 MRI 是扫描镜头时(特别是如果它们显示为 SC),它只会是一帧,
Ruby 肯定会在运行时存储此类信息,因为它会打印在堆栈跟踪中 - 但似乎没有任何明显的方法来访问它。有解决办法吗? (除了 grep 源,或将无意义的参数传递给方法以希望获得堆栈跟踪) 最佳答案 在
在其他语言中,通常有多种内存回收的可能性: 标记对象然后移除它们 显式保留和释放 计算对对象的引用 内部堆配置 Ruby 是如何工作的? 最佳答案 垃圾收集器 Ruby 1.8 实际上非常糟糕。每 7
我已经将 Ubuntu 11.04 上的 Rails 3.0.10/MRI 应用移植到 Ubuntu 11.04 上的 JRuby 1.6.4。我的目标是到达一个地方,我只需执行以下操作即可在 JRu
在我看来,用 Ruby MRI 1.8.7 编写文件是完全线程安全的。 示例 1 - 完美结果: File.open("test.txt", "a") { |f| threads = [] 1
在做一些基准测试来回答关于连接数组的最快方法的 this 问题时,令我惊讶的是,当我使用 jRuby 进行相同的基准测试时,测试速度要慢得多。 这是否意味着关于 jRuby 比 MRI Ruby 更快
在 MRI 中,似乎 rb_id2str()当您调用 Symbol#to_s 时负责完成所有工作.我惊讶地发现这是一个极其神秘的函数,而我认为这是一个相当直接的操作。 我正在寻找有关此功能的详细说明。
我是一名优秀的程序员,十分优秀!