- Workers of the World
- Lock the Door Behind You
- On One Condition
- Reading, Writing, and Arithmetic
- Loose Threads
Lock the Door Behind You
Because threads run in the same address space, they can be seen as an extreme case of processes using shared memory. In the previous example, our threads were independent. The only time they touched each other was at creation and destruction. This isn’t always the case, however; sometimes you want two threads to access the same variable or use the same resource.
Part 1 of this series discussed how to use semaphores as mutexes for protecting shared memory between processes. The POSIX threading API defines thread-level mutexes. A mutex is a simple lock; only one thread can hold it at once, and once it’s released another thread waiting on it is awakened (see Listing 2).
Listing 2 mutex.c.
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <math.h> #include <unistd.h> pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void * run_thread(int number) { for(unsigned int i=0 ; i<10 ; i++) { pthread_mutex_lock(&mutex); printf("Thread %d sleeping...\n",number); sleep(1); printf("Thread %d waking...\n",number); pthread_mutex_unlock(&mutex); } return 0; } int main(void) { pthread_t thread1, thread2; pthread_create(&thread1, NULL, (void*(*)(void*))run_thread, (void*)1); pthread_create(&thread2, NULL, (void*(*)(void*))run_thread, (void*)2); pthread_join(thread1, NULL); pthread_join(thread2, NULL); return 0; }
In the previous example, two threads run in parallel. Each one acquires a mutex and sleeps for a second. Watching the output from this, you’ll see the following:
Thread 1 sleeping... Thread 1 waking... Thread 2 sleeping... Thread 2 waking...
At no point can these threads overlap. This construction can be used to protect critical sections in your code—parts where only one thread should be running at once. A typical example would be functions that get and set parts of a shared data structure.
Note that our mutex was created with PTHREAD_MUTEX_INITIALIZER. This is used only for creating mutexes statically. It doesn’t actually create the mutex; rather, it sets a flag in the data structure that stores the mutex, causing the first mutex operation called to initialize it. If you’re creating mutexes at runtime, you should use the pthread_mutex_init(3) function instead.