This site will look much better in a browser that supports web standards, but is accessible to any browser or Internet device.

Anomaly ~ G. Wade Johnson Anomaly Home G. Wade Home

January 15, 2004

Thread death

There is a subtle aspect of threads that may be worth exploring having to do with the concept of joining. Many threading systems support the possibility of waiting until a thread completes in order to retrieve its exit state. This is often started through a function called join(). In order to support this feature, a terminating thread may remain in memory until it is joined. This allows the join() function to work the same way (except without suspending) on a thread that is running or on one that has already finished.

Unfortunately, these dead threads consume system resources. At a minimum, they are taking up a spot in the thread maintenance data structures in the OS. They may also retain memory or other resources. In order to clean up these resources, the thread must be join()ed.

This can be inconvenient. In some cases, the threads are launched without any need to know how they exited. Some threading systems allow setting the state of a thread such that it is not joinable. This means that when it finishes executing, the thread will be discarded automatically.

A related issue has to do with exitting the program and running threads. In a multithreaded program, how does the system decide when to exit the process that contains these threads? There are basically three approaches:

  • The process exits when all threads exit.
  • The process exits when the main thread exits.
  • The process exits when all important threads exit.

The first can be inconvenient, even if it is easy to understand. The second is easy to mess up. For example, you can launch all of your worker threads in the main thread and then exit because the main thread has nothing left to do. Suddenly, the program is gone and no work got done. This can be solved by having the main thread wait for some signal from other threads that it is time to shut down.

The Java threading library takes a different approach. Normally, a program runs until all of its threads are dead. However, a thread can be marked as a daemon. In the Java terminology, the process exits when all non-daemon threads are dead. This allows one to choose any of the other two approaches or something else entirely.

The only problem I have with this approach is the name. A daemon thread or process has certain connotations on a Unix-like system. I don't think the fact the thread will not keep the program alive is the defining characteristic of a daemon.

Posted by GWade at January 15, 2004 11:03 AM. Email comments