不,块(procs、lambdas)不在它们自己的线程中运行。这里的问题是 Ruby 保存和恢复$SAFE
每个方法(和 proc)调用的级别。如果您尝试使用另一个变量,例如$FOO
,您会得到预期的结果:
> x = ->{ $FOO = 1; puts $FOO }.call; puts $FOO
1
1
你可以看到这是在哪里实现rb_method_call
的proc.c
:
const int safe_level_to_run = 4 /*SAFE_LEVEL_MAX*/;
safe = rb_safe_level();
if (rb_safe_level() < safe_level_to_run) {
rb_set_safe_level_force(safe_level_to_run);
}
// ...
// Invoke the block
// ...
if (safe >= 0)
rb_set_safe_level_force(safe);
保存安全级别,如果小于4,则设置为4。然后调用该块,如果修改前的安全级别> = 0,则恢复为之前的状态。您可以通过以下方式看到这一点:
> puts $SAFE; ->{ puts $SAFE; $SAFE = 1; puts $SAFE }.call; puts $SAFE
0
0
1
0
$SAFE
是 0 进入块,并且块被执行,然后在块退出时恢复为 0,尽管在块内被修改为 1。