A thread is a separate flow of execution in a program. A single program can have multiple threads running within the same address space. Multithreaded programs share data in common address space. Access to shared data must be mediated through the use of mutual exclusion locks. Mechanics of mutual exclusion require hardware support -- testAndSet instruction. int testAndSet( int * target ) // ATOMIC pseudocode { int rv = *target; *target = 1; return rv; } What is really protected here? Data in Critical Sections. int mylock; for( ;; ) // pseudocode { // some code while ( testAndSet( &mylock ) ); // critical section mylock = 0; // other code } Mutex locks have an owner and a queue of waiting threads. The initial state of a mutex lock is unlocked. Unlocked mutex locks have no owner. Once locked, a mutex can only be unlocked by its owner. Multiple locks locked in the wrong order can cause deadlock. Lock all locks in a canonical locking order. ________________________________________________________________________ Basic POSIX mutex operations are: - initialize - lock - unlock - trylock - destroy POSIX functions return 0 on success, some sort of errno on failure. Link with -Kthread to get POSIX library (see Makefile). UNIX handles kernel-level and user-level, but Linux handles only one. #include int pthread_mutexattr_init( pthread_mutexattr_t * attr ); initialize a pthread_mutexattr_t with default values: PTHREAD_PROCESS_PRIVATE (i.e. used only in this process) PTHREAD_MUTEX_DEFAULT - Attempting to relock mutex results in undefined behavior. - Attempting to unlock mutex if it was not locked by the calling thread results in undefined behavior. - Attempting to unlock mutex that is not locked results in undefined behavior. other attributes include: PTHREAD_PROCESS_SHARED (i.e. used between multiple processes) PTHREAD_MUTEX_NORMAL - Attempting to relock mutex causes deadlock. - Attempting to unlock a mutex that it has not locked or a mutex which is unlocked, undefined behavior results. int pthread_mutexattr_destroy( pthread_mutexattr_t * attr ); destroy the pthread_mutexattr_t. int pthread_mutex_init( pthread_mutex_t *, const pthread_mutexattr_t * ); initialize a pthread_mutex_t. Second arg can be zero, meaning assume default attributes. Can also use PTHREAD_MUTEX_INITIALIZER for default behavior. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int pthread_mutex_lock( pthread_mutex_t * ); If mutex is unlocked, lock it and make the calling thread the owner. If mutex is locked, then block calling thread until the mutex is unlocked. Does not return until called has the lock. int pthread_mutex_trylock( pthread_mutex_t * ); If mutex is unlocked, lock it and make the calling thread the owner. If mutex is locked, return EBUSY immediately without blocking or acquiring the lock. int pthread_mutex_unlock( pthread_mutex_t * ); If mutex is not locked, no effect. If locked, but caller is not owner then return EPERM. else unlock the mutex. int pthread_mutex_destroy( pthread_mutex_t * ); Destroy the mutex. Don't use it after it's destroyed. Good idea to ensure mutex is unlocked before destruction.