此问题来自此代码段:
lambda do
$SAFE = 2
puts $SAFE
end .call
puts $SAFE
结果是:
2
0
$SAFE
是一个全局变量,所以我无法理解这一点。我探索了一段时间,然后发现$SAFE
是一个线程局部变量,而不是真正的全局变量。
好的,我能理解这一点:
k = Thread.new do
$SAFE = 2
puts $SAFE
end
k.run
1000000.times {}
puts $SAFE
但是等一下,该块会打开另一个线程来运行它吗?
答案 0 :(得分:1)
不,块(procs,lambdas)不会在自己的线程中运行。这里的问题是Ruby在每个方法(和proc)调用周围保存并恢复$SAFE
级别。如果您使用其他变量(例如$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。