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

Accessing thread variables of threads stored in 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 线程变量?

您在这里看到的是竞争条件。您试图在线程主体 运行 之前读取线程变量

比较以下:

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 运行 资源不足)

这与我听说的 "number one rule of async" 相关,即您无法从同步方法中获取异步方法的 return 值。通常的处理方法是使用 "callback",Ruby 可以用 yield / 块的形式来处理。

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