Your Web Guide to POSIX Threads
Threads are lightweight processes and a unit of execution. To understand the distinction between threads and processes, the relation between Mach tasks and UNIX processes and threads should be examined. In UNIX, a process handles both an executing program and a bundle of resources, such as a descriptor table and file. In Mach, threads handle all executing units and tasks contain a bundle of resources. All threads share the resources with a given task. A UNIX process in the Mach tasks is patterned as a single task with a thread.
POSIX threads are known as pthreads and follow POSIX standards for creating and managing thread operation. Basic thread operation involves thread creation, synchronization, termination, data management, process interaction, and scheduling.
The function pthread_create creates a new thread, which takes four arguments. The arguments are thread variable, thread attribute, function call, and function argument. A thread attribute specifies minimum stack size and execution of a program begins at the function stated in pthread_create. The execution starts at a different point to avoid the multiple threads sharing the same resources to execute the same instructions. The function pthread_exit kills the thread and if the thread is not detached, the thread value and id may be used by another thread by calling the function pthread_join. The function pthread_delay_np delays a thread where np stands for not process.
POSIX standards provide two synchronization expressions: the condition and the mutex variable. Mutexes are the lock primitives that are used to manage access to a shared resource. If a mutex is not needed in a program, then it is killed by calling the function pthread_mutex_destroy (&mutex). The mutex primitive has two states: locked and unlocked and the proper use of this guarantees the elimination of the race condition. The condition variable allows a thread to block and wait for the signal from another thread. When the thread receives signal, it awakens and obtains the lock on the related mutex. The spin-lock problem can be eliminated by joining the signal and mutex.
Coordinating Activities with Semaphores
The semaphore operations are semaphore_init, semaphore_up, semaphore_down, semaphore_decrement, and semaphore_destroy. The up and down functions are traditional semaphore semantics. The down operation blocks the semaphore with value less than or equal to zero. The up operation increments the semaphore value and the init function is the prior function call to use semaphores. Initially, the semaphore value is incremented with a value of one.
The destroy function releases the semaphore that is no longer used. All the semaphore function has one argument that is a pointer to the semaphore object. The function decrement decreases the semaphore value and it is a non-blocking function.
Pthread header file must be included to compile the pthreads. The function pthread_join allows a thread to wait for another thread to exit. If some_thread does not exist, then pthread_join may cause an error. All the pthread functions return -1 on an occurrence of an error. The semaphore library prints the error message and exit upon errors. Other useful functions are pthread_yield (), pthread_t me where me is the pthread_self (), pthread_t thread, and pthread_detach (thread).
For additional information on the POSIX threads refer to the following sites: