访问实例变量中存储的线程的线程变量

时间:2019-06-21 03:38:37

标签: ruby multithreading instance-variables

这是预期的

t = Thread.new{
 Thread.current[:rabbit] = 'white'
}

#####  t[:rabbit] = white

但是我不明白这一点:

class Whatever
 def initialize
  @thd = Thread.new{
   Thread.current[:apple] = 'whatever'
  }
 end

 def apple
  @thd[:apple] 
 end

 def thd
  @thd
 end
end

我想访问它们,为什么它们nil

Whatever.new.apple # nil

Whatever.new.thd[:apple] # nil

Whatever.new.thd.thread_variable_get(:apple) # nil

为什么会这样?如何访问@thd线程变量?

1 个答案:

答案 0 :(得分:4)

您在这里看到的是比赛条件。您正在尝试在运行线程主体之前读取线程变量

比较以下内容:

w = Whatever.new
w.apple
# => nil

w = Whatever.new
sleep 0.1
w.apple
# => "whatever"

无论线程主体是否及时Whatever.new.apple运行都是随机的,对我来说似乎发生了0.1%的时间,但这在其他计算机上可能有所不同

1000.times.
  map { Whatever.new.apple }.
  each_with_object(Hash.new(0)) { |val, memo| memo[val] += 1 }
# => {nil=>999, "whatever"=>1}

2000.times.
  map { Whatever.new.apple }.
  each_with_object(Hash.new(0)) { |val, memo| memo[val] += 1 }
# => {nil=>1998, "whatever"=>2}

(注意:由于大量的线程产生会导致我的IRB耗尽资源,因此我无法尝试进行更多的迭代)

这与我所听到的被描述为“异步的第一规则”有关,也就是说,您无法从同步方法获得异步方法的返回值。处理此问题的常用方法是使用“回调”,Ruby可以使用yield /块的形式来实现。

我建议寻找有关如何在Ruby中进行异步编程的教程。