【发布时间】:2015-11-04 16:05:19
【问题描述】:
今天我试图向同事解释 ||= 在 MRI 中不是线程安全的。我想我会看一下 Ruby 源代码来尝试看看我是否可以指出 Ruby 调度程序可以切换线程上下文的位置,但是我在导航代码时遇到了问题。我希望更有经验的人可以指导我浏览被击中的文件。
到目前为止,我知道 Bison 使用 parse.y 并生成一个调用一些底层函数的 parse.c 文件。我看到 || 被解析为 tOROP 但是我对接下来发生的事情有点迷茫
还有像 Ripper 这样的工具,我可以使用它来简化这个过程吗? (如果有人能指出 Ripper 源代码的定义位置,那将会很有帮助)
【问题讨论】:
-
就像
x += 1是非原子的一样。它需要读取、比较和(条件)赋值。x ||= y实际上是x = x || y或x = y unless (x),具体取决于您想要获得的具体程度。请注意,在这两种情况下,都需要在分配之前进行读取和比较(不是 false)。在那个间隙中,任何事情都可能发生。您可能想查看 MRI 表达该语句的字节码,以了解内部发生了什么。 -
MRI 的
ruby有一个--dump选项。我认为您正在寻找--dump yydebug,但您可能也对parsetree或insns感兴趣。 -
@cremno 非常好!这绝对是一个很大的帮助
ruby -e "@hello ||= 'hi'" --dump parsetree看起来应该很有用 -
我认为它可能在 MRI(但不是 JRuby)中是“意外”线程安全的。我明白你在问什么,我不知道 C 代码在哪里指向你,但我以前看过关于它的文章,也许你可以找到谷歌搜索。在 MRI 中,GIL 仅在某些点发布是对的,
||=可能会意外地成为线程安全的,但即使是这样,它也是一个实现细节,可能会发生变化,并且在其他解释器中并不安全。 -
线程安全与解析器无关。别看那里了。 ||= 被重写为一系列操作(查看汇编代码)并且该序列可以被中断,在此期间另一个线程可以更改为条件读取的值。
标签: ruby