考虑下面的代码段。在其中,我定义了一个名为doit
的方法,随后从两个不同的线程调用。
与我的预期相反,方法中的t.object_id
会不断返回两个不同的ID,就好像每个线程对方法的调用在内存中都有自己的空间一样。
我期望发生的是,在进入该方法的第二个线程上,它将替换先前定义的哈希值,导致在其余时间打印相同的对象ID。换句话说,我认为会有一个Hash的实例。
可以说,这可能表明方法的第一个条目中的循环会阻止对其的任何后续访问,但显然情况并非如此。
那么方法的处理是什么?来自单独线程的每次调用是否在内存中都有自己的副本?理解这个的正确方法是什么?
def doit
t = Hash.new
puts t.object_id
loop do
sleep 1
puts t.object_id
end
end
t1 = Thread.new { doit }
t2 = Thread.new { doit }
t1.join
t2.join
举例来说,这是输出:
21329316
21327684
21329316
21327684
21329316
21327684
21327684
21329316
21327684
21329316
21327684
21329316
答案 0 :(得分:2)
t
是doit
的局部变量,仅在方法的范围中声明。每次执行都会收到自己的t
。
如果您要分享 t
,请将其声明为实例成员@t
:
def doit
@t = Hash.new
puts @t.object_id
loop do
sleep 1
puts @t.object_id
end
end
t1 = Thread.new { doit }
t2 = Thread.new { doit }
t1.join
t2.join
现在你的输出看起来像这样:
15223760
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580
答案 1 :(得分:1)
线程与它无关。 t
是每次调用doit
时初始化的局部变量 - 因此每次调用都会获得自己的t
。请注意,删除线程会产生相同的结果,尽管不是交错的:
def doit
t = Hash.new
t.object_id
end
doit #=> 21329316
doit #=> 21327684