B Pthreads: Explicit Use of Threads
Pthreads, also known as POSIX Threads, as specified by the IEEE POSIX 1003.1c standard, provides fairly portable support for multi-threading. It uses a library interface that enables the user to explicitly manipulate threads, for instance, to start, synchronize, and terminate threads. The programmer fully controls when threads are created and what work they perform, and this provides great flexibility, albeit at the cost of greater complexity than the OpenMP approach discussed in Appendix C. In the following we will give a brief introduction to programming with Pthreads; for more complete information, good guides to multi-threaded programming and Pthreads can be found elsewhere.1,2
We will illustrate programming with Pthreads using the simple example shown in Figure B.1 in which a number of tasks are distributed between two threads. To use Pthreads, it is necessary to include the Pthreads header file pthread.h, which declares the function signatures for the Pthreads library along with the required data types. A few of the most commonly used Pthreads functions are listed in Table B.1, and their arguments are described in Table B.2. A key feature required by a Pthreads program is a start routine, which is the function that will be run by the threads. In our example, the start routine for the created threads is the worker function. Having defined a start routine, threads can be created by means of the pthread_create function call, which takes the start routine as one of its arguments. In our example program, the threads running the worker routine obtain their tasks from a shared pointer to a variable, which is named task_iter and is of type task_iterator_t. The task_iter variable contains an integer (next_task) that gives the next unassigned work unit, an integer that gives the last work unit (max_task), and a mutual exclusion lock (mutex). Because all start routines must have the same signature, arguments are passed using a pointer to void, and the start routine must cast this into whatever type is needed. In our example, the task_iter variable is the argument for the start routine.