POSIX threads (pthread) are a major specification for a threading API on POSIX-compatible systems, like UNIX or Linux. By default, Windows doesn’t support pthreads.

Mutexes

Mutexes are provided with a basic pthread_mutex_t type. We create an instance of the mutex type for each lock we want to implement.

We have to first initialise the mutex, to prevent uninitialised behaviour. We can either use the pthread_mutex_init function, or we can set the mutex equal to a special PTHREAD_MUTEX_INITIALIZER macro. Both are equivalent.

API

  • Basic threads
    • pthread_create:
      • start_routine: function pointer, takes a single void pointer (type-agnostic pointer to memory) and returns a pointer
    • pthread_join: threaded equivalent of the wait syscall (for processes).
    • pthread_exit: threaded equivalent of the exit syscall.
    • pthread_detach: mark thread as detached.
  • Mutex
    • pthread_mutex_init: initialises a mutex. Must be called on a mutex to initialise it to something.
      • pthread_mutex_t *restrict mutex
      • const pthread_mutexattr_t *restrict attr: desired attributes. If we want a default mutex, we can pass NULL.
    • pthread_mutex_lock
    • pthread_mutex_unlock
  • Condition variables
    • pthread_cond_init
    • pthread_cond_destroy
    • pthread_cond_signal: wakes up the first thread in the queue.
    • pthread_cond_broadcast: wakes up all threads in the queue.
    • pthread_cond_wait: adds a thread to the queue. Must be paired with a mutex so enqueueing operations are atomic.
      • It doesn’t contain data races — it adds itself to the queue for the condition variable, unlocks the mutex, then gets blocked (it can no longer be scheduled to run).
      • The thread calling wait needs another thread to call signal or broadcast. If it’s selected, it gets unblocked, tries to lock the mutex again, and wait returns when it gets it.
    • pthread_cond_timedwait