10.3: Mutual exclusion
- Page ID
- 40636
We can make the queue thread safe with a mutex. This version of the code is in queue_mutex.c
.
First we add a Mutex
pointer to the queue structure:
typedef struct { int *array; int length; int next_in; int next_out; Mutex *mutex; //-- this line is new } Queue;
And initialize the Mutex
in make_queue
:
Queue *make_queue(int length) { Queue *queue = (Queue *) malloc(sizeof(Queue)); queue->length = length; queue->array = (int *) malloc(length * sizeof(int)); queue->next_in = 0; queue->next_out = 0; queue->mutex = make_mutex(); //-- new return queue; }
Next we add synchronization code to queue_push
:
void queue_push(Queue *queue, int item) { mutex_lock(queue->mutex); //-- new if (queue_full(queue)) { mutex_unlock(queue->mutex); //-- new perror_exit("queue is full"); } queue->array[queue->next_in] = item; queue->next_in = queue_incr(queue, queue->next_in); mutex_unlock(queue->mutex); //-- new }
Before checking whether the queue is full, we have to lock the Mutex
. If the queue is full, we have to unlock the Mutex
before exiting; otherwise the thread would leave it locked and no other threads could proceed.
The synchronization code for queue_pop
is similar:
int queue_pop(Queue *queue) { mutex_lock(queue->mutex); if (queue_empty(queue)) { mutex_unlock(queue->mutex); perror_exit("queue is empty"); } int item = queue->array[queue->next_out]; queue->next_out = queue_incr(queue, queue->next_out); mutex_unlock(queue->mutex); return item; }
Note that the other Queue
functions, queue_full
, queue_empty
, and queue_incr
do not try to lock the mutex. Any thread that calls these functions is required to lock the mutex first; this requirement is part of the documented interface for these functions.
With this additional code, the queue is thread safe; if you run it, you should not see any synchronization errors. But it is likely that the consumer will exit at some point because the queue is empty, or the producer will exit because the queue is full, or both.
The next step is to add condition variables.