介绍性 Ruby 线程问题

Introductory Ruby Threading Issue

这几天一直在学习Ruby,在线程的实现上遇到了一些问题。我以前用其他语言编程过(主要是 Java 和 C),但我仍然无法弄清楚问题出在哪里。我在 Ubuntu 服务器 14.10 上运行 ruby 2.1.2p95。有问题的代码来自 Mr. Neighborly's Humble Little Ruby Book:

mate = Thread.new do
  puts "Ahoy! Can I be dropping the anchor sir?"
  Thread.stop
  puts "Aye sir, dropping anchor!"
end

Thread.pass

puts "CAPTAIN: Aye, laddy!"

mate.run
mate.join

输出应该是:

Ahoy! Can I be dropping the anchor sir?
CAPTAIN: Aye, laddy!
Aye sir, dropping anchor!

但是,我收到了以下加入和死锁错误:

CAPTAIN: Aye, laddy!
Ahoy! Can I be dropping the anchor sir?
ex2.rb:12:in `join': No live threads left. Deadlock? (fatal)
    from ex2.rb:12:in `<main>'

我在使用其他资源的其他线程示例时也遇到过错误,并尝试在其他 Ubuntu 机器上运行示例以及尝试 Ruby 2.2。我错过了一个明显的概念吗? Ruby 的最近修订版是否发生了某些会认为示例已过时的更改?感谢您的帮助!

Has something changed in recent revisions of Ruby that would deem the examples out-of-date?

是的。看起来这本书是 written for Ruby 1.8, which used green threads。 Ruby 1.9 及更高版本使用 native 线程(线程由 OS 调度)。

比较 Thread.pass method in Ruby 1.8.7 的文档:

Invokes the thread scheduler to pass execution to another thread.

在 Ruby 2.1.2(您正在使用的版本)中,this methods documentation 如下所示:

Give the thread scheduler a hint to pass execution to another thread. A running thread may or may not switch, it depends on OS and processor.

因此在当前版本中,调度不像 Ruby 1.8.7 中那样具有确定性,OS 可以随意忽略对 Thread.pass 和 运行 首先是主线程,这会导致问题。

运行 我机器上的这个脚本(Mac OS 10.9,Ruby 2.2.0)我得到了两个结果,有时它有效,我看到:

Ahoy! Can I be dropping the anchor sir?
CAPTAIN: Aye, laddy!
Aye sir, dropping anchor!

其他时候失败:

CAPTAIN: Aye, laddy!
Ahoy! Can I be dropping the anchor sir?
capt-thread.rb:12:in `join': No live threads left. Deadlock? (fatal)
    from capt-thread.rb:12:in `<main>'