Previous Next

Overview - Threads

Threads as used specifically in DCE applications raise several obvious policy issues which may be summarized, roughly, as follows:

· When to use multiple threads

· How many threads to use

· What scheduling and priority attributes to apply

These issues are covered in Thread Use Policy.

Beyond these obvious policy questions, however, threads raise a tricky issue for a programming policy guide because it is not always clear where the line between mechanism and policy lies. Multithreaded programming in general requires a number of practices that are likely to be unfamiliar and unintuitive to many programmers, and errors arising from failure to follow these practices can be obscure, infrequent, and difficult to reproduce. One result is that an incorrect program can easily appear to be correct.

A typical case is a program that performs the following sequence of steps:

pthread_create(&thread . . .);
pthread_setprio(thread . . .);

From the point of view of a single thread, this may seem like a logical sequence of steps, yet it contains a fundamental error: the spawned thread may well have begun to execute, or even have terminated, by the time the call to pthread_setprio( ) occurs. The result is a program whose behavior is indeterminate, and which may fail unpredictably. The correct procedure is to use a thread attributes object to set the thread's priority when it is created.

Strictly speaking, this is really a programming mechanism issue, since the failure to follow the rule results in an incorrect program. However, errors of this type can be obscure: in fact, the resulting program might never fail due to this error. There are many such error possibilities in a multithreaded program that can result in all kinds of deadlocks, race conditions, and data corruption. Yet these errors can sometimes be so obscure as to be extremely difficult to analyze a priori, and failures may occur so rarely as to be virtually unreproducible.

As a result, correct use of threads mechanisms requires following a set of general rules designed to avoid errors that may or may not occur in specific cases. For example, locks must be taken and released in the same strict order. Rules like this are in not enforced by the thread programming mechanisms, and failure to follow them will not always result in program failures. In fact, failure to obey these rules may not always be a programming error: depending on the program, it is certainly possible that there is no possible execution path where failure to follow a rule would result in an error (although this might be difficult to establish a priori).

As a result, such rules have in some sense the flavor of policy recommendations: they are a set of disciplines for avoiding certain classes of problems which threads programmers can assume to exist, in general, even though they might not arise in specific cases. Because of this, and because these rules may be unfamiliar to many programmers, it seems wise to repeat them in summary form in this policy guide. Moreover, because DCE client and server applications are implicitly multithreaded, even when the application itself makes no thread related calls, it is also important to identify when application code must be thread safe. These issues are covered in Thread Safety.

The remaining topics cover a variety of specific policy and usage issues relating to DCE threads. Thread handles and thread-private data are discussed in Thread Handles and Storage for Thread Specific Data.

Cancels and signals introduce a number of specific semantic issues that applications must be aware of when programming in a multithreaded environment. These are covered in Canceling Threads and Signals respectively. Finally, DCE introduces the concept of an RPC thread. This is intended to extend the semantics of a local thread of execution across two address spaces in the course of an RPC. However, the extension is not entirely transparent, and applications need to be aware of the semantic peculiarities of RPC threads. These are covered in RPC Threads and RPC Threads and RPC Cancel Semantics.