Connor
Connor

Reputation: 43

Introductory Ruby Threading Issue

I've been learning Ruby for the past few days, and I've run into a few issues concerning the implementation of threads. I've programmed in other languages before (mainly Java and C), and I still couldn't figure out what the issue is. I'm running ruby 2.1.2p95 on Ubuntu Server 14.10. The code in question is from 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

The output should be:

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

But instead, I'm receiving the following join and deadlock error:

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>'

I've run into errors with other threading examples from other resources as well, and have tried running the examples on other Ubuntu machines as well as trying Ruby 2.2. Is there a blatant concept that I'm missing out on? Has something changed in recent revisions of Ruby that would deem the examples out-of-date? Thank you for your help!

Upvotes: 4

Views: 712

Answers (1)

matt
matt

Reputation: 79733

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

Yes. It looks like this book was written for Ruby 1.8, which used green threads. Ruby 1.9 onwards uses native threads (where the threads are scheduled by the OS).

Compare the documentation for the Thread.pass method in Ruby 1.8.7:

Invokes the thread scheduler to pass execution to another thread.

In Ruby 2.1.2 (the version you are using), this methods documentation looks like this:

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.

So in current versions the scheduling is not deterministic in the way it was in Ruby 1.8.7, the OS is free to ignore the call to Thread.pass and run the main thread first, which causes the problems.

Running this script on my machine (Mac OS 10.9, Ruby 2.2.0) I get both results, sometimes it works and I see:

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

Other times it fails with:

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>'

Upvotes: 2

Related Questions