Ruby线程回调奇怪的行为

时间:2012-08-07 11:42:17

标签: ruby

创建一个包含一些线程,执行任务并最终调用回调方法的类是我目前的目标,在这条路上没什么特别的。

我的实验类会对给定IP的特定端口进行一些连接检查,以便为我提供状态信息。

所以我的尝试:

check = ConnectionChecker.new do | threads |
   # i am done callback
end

check.check_connectivity(ip0, port0, timeout0, identifier0)
check.check_connectivity(ip1, port1, timeout1, identifier1)
check.check_connectivity(ip2, port2, timeout2, identifier2)

sleep while not check.is_done

也许不是最好的方法,但总的来说它适合我的情况。

所以发生了什么:

在我的课程中,我会存储一个回调,执行操作并执行内部操作:

Thread.new - >成功/失败 - >完成时标记为已完成 - >呼叫回叫:

 class ConnectionChecker

   attr_reader :is_done

   def initialize(&callback)
     @callback     = callback
     @thread_count = 0
     @threads      = []
     @is_done      = false
   end

   def check_connectivity(host, port, timeout, ident)
     @thread_count += 1
     @threads << Thread.new do

       status = false
       pid    = Process.spawn("nc -z #{host} #{port} >/dev/null")

       begin
         Timeout.timeout(timeout) do
           Process.wait(pid)
           status = true
         end
       rescue Process::TimeoutError => e
         Process.kill('TERM', pid)
       end

       mark_as_done
       #returnvalue for the callback.
       [status, ident]
     end
   end

   # one less to go..
   def mark_as_done
     @thread_count -= 1
     if @thread_count.zero?
       @is_done = true
       @callback.call(@threads)
     end
   end
 end

这段代码 - 是的,我知道没有启动方法所以我必须相信我会立刻称之为 - 工作正常。

但是当我换掉这两行时:

  @is_done = true
  @callback.call(@threads)

  @callback.call(@threads)
  @is_done = true

然后是最后一行,

sleep while not check.is_done

成为无限循环。调试显示我正确调用了回调,当我检查is_done的值时,它总是false。由于我没有把它关闭,我想知道为什么会发生这种情况。

回调本身也可以为空,is_done仍为false(因此没有错误捕获的异常)。

在这种情况下,我注意到最后一个线程处于运行状态。由于我没有要求线程的价值,我只是不在这里。

有关此问题的任何文档/信息?此外,它的名称也没问题。

1 个答案:

答案 0 :(得分:1)

尝试使用Mutex确保线程安全:)