Chapter 7. Ruby Threads
IN THIS CHAPTER
He draweth out the thread of his verbosity finer than the staple of his argument.
William Shakespeare, Love's Labours Lost, act 5, scene 1
Threads are sometimes called lightweight processes. They are nothing more than a way to achieve concurrency without all the overhead of switching tasks at the operating system level. (Of course, the computing community isn't in perfect agreement about the definition of threads; but we won't go into that.)
Ruby threads are user-level threads and are operating system independent. They will work on DOS as well as on Unix. There will definitely be a performance hit, however, which will also vary by operating system.
Threads are useful in circumstances where, for instance, there are separate pieces of code that naturally function independently of each other. They are also used when an application spends much of its time waiting for an event. Often, while a thread is waiting, another one can be doing useful processing.
On the other hand, there are some potential disadvantages in the use of threads. The decrease in speed has to be weighed against the benefits. Also, there are cases in which access to a resource is inherently serialized, so threading doesn't help. Finally, there are times when the overhead of synchronizing access to global resources exceeds the saving due to multithreading.
For these and other reasons, some authorities claim that threaded programming is to be avoided. Indeed, concurrent code can be complex, error-prone, and difficult to debug. But we will leave it to you when it is appropriate to use these techniques.
The difficulties associated with unsynchronized threads are well-known. Global data can be corrupted by threads attempting simultaneous access to those data. Race conditions can occur wherein one thread makes some assumption about what another has done already; these commonly result in "non-deterministic" code that might run differently with each execution. Finally, there is the danger of deadlock, wherein no thread can continue because it is waiting for a resource held by some other thread that is also blocked. Code written to avoid these problems is referred to as thread-safe code.
Not all of Ruby is thread-safe, but synchronization methods are available that will enable you to control access to variables and resources, protect critical sections of code, and avoid deadlock. We will deal with these techniques in this chapter and give code fragments to illustrate them.