Here’s a video about threads in Ruby - how do you code them? What are the problems with them?
I’m planning a few more short videos about Ruby concurrency. I don’t think enough people
have a good grasp of the tradeoffs and problems of running more than one chunk of code at
once, in Ruby or in general.
I’m also still learning Camtasia and
the rest of the video toolchain. So I hope I’ll look back in a few months and think,
“wow, this looks really bad now!”
In the mean time, enjoy! Here’s a transcript:
Ruby supports threads, of course. Modern Ruby, anything 1.9 and higher, uses
the normal kind of threads for your operating system, or JVM threads if you’re
Here’s the code to make that happen.
The code inside the Thread.new block runs in the thread, while your main
program skips the block and runs the join. “Join” means to wait for the
thread to finish - in this case, it waits up to 30 seconds since that’s what
we told it. With no argument, join will wait forever.
You’ll probably want a begin/rescue/end inside your thread to print a message
if an uncaught exception happens. By default, Ruby just lets the thread die
silently. Or you can set an option to have Ruby kill your whole program, but I
prefer to print a message.
In “normal” Ruby, Matz’s Ruby, there’s a Global Interpreter Lock. Two threads
can’t run Ruby code at the same time in the same process. So most Ruby threads
are waiting for something to complete, like an HTTP request or a database
What are Ruby threads good for if there’s a global lock? In Matz’s Ruby,
you’ll mostly want to use them for occasional events. RabbitMQ messages,
timeouts, and Cron-style timed jobs are all good.
Since you can only have one thread doing real work in Ruby at once, threads
are best when your process is mostly idle.
JRuby and Rubinius users can chuckle here. Their Ruby handles multiple Ruby
threads working at the same time without a hiccup.
So what problems do you sometimes see with Ruby threads?
With the Global Interpreter Lock, threads can switch back and forth between
CPUs, sometimes very often. If you see Ruby threads performing horribly in
production with Matz’s Ruby or using way too much CPU, try locking the thread
down to a single CPU. Your operating system has commands for that — Google
Next, if the main thread dies or finishes, your program ends. That’s a
feature, but sometimes it’s surprising. To have your main thread of execution
stick around, use join on the other threads to let them finish.
And of course an unhandled exception in a child thread kills only the child
thread, and it does it completely silently. Use a begin/rescue/end to print
errors to console or set the Ruby option to kill the main program when a child
thread dies from an unhandled exception.