Chapter 13. Threads in Ruby
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 is not 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 work on DOS as well as on UNIX. There will definitely be a performance hit, however, which also varies by operating system.
Threads are useful in circumstances where, for instance, separate pieces of code naturally function independently of each other. They are also used when an application spends much of its time waiting for an event. Often while one thread is waiting, another 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, in some cases access to a resource is inherently serialized, so that threading doesn't help. Finally, sometimes 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 the reader to decide when it is appropriate to use these techniques.
The difficulties associated with unsynchronized threads are well-known. Global data may be corrupted by threads attempting simultaneous access to those data. Race conditions may occur wherein one thread makes some assumption about what another has done already; these commonly result in "nondeterministic" code that may 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, which 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 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.