The solution to the job queue race condition problem is to let only one thread access the queue of jobs at a time.
Implementing this requires support from the operating system, mutexes, short for MUTual EXclusion locks.
A mutex is a special lock that only one thread may lock at a time. If a thread locks a mutex and then a second thread also tries to lock the same mutex, the second thread is blocked, or put on hold.
To create a mutex, create a variable of type pthread_mutex_t and pass a pointer to it to pthread_mutex_init.
The second argument to pthread_mutex_init is a pointer to a mutex attribute object, which specifies attributes of the mutex.
The mutex variable should be initialized only once.
Another simpler way to create a mutex with default attributes is to initialize it with the special value PTHREAD_MUTEX_INITIALIZER. No additional call to pthread_mutex_init is necessary.
A thread may attempt to lock a mutex by calling pthread_mutex_lock on it. If the mutex was unlocked, it becomes locked and the function returns immediately.
More than one thread may be blocked on a locked mutex at one time. When the mutex is unlocked, only one of the blocked threads (chosen unpredictably) is unblocked and allowed to lock the mutex; the other threads stay blocked.
A call to pthread_mutex_unlock unlocks a mutex. This function should always be called from the same thread that locked the mutex.
The following code (see Fig. 5.9) shows another version of the job queue example. Now the queue is protected by a mutex. http://siber.cankaya.edu.tr/SystemsProgramming/cfiles/job-queue2.cjob-queue2.c
Figure 5.9:
Job Queue Thread Function, Protected by a Mutex
Note that if the queue is empty (that is, job_queue is null), we don't break out of the loop immediately because this would leave the mutex permanently locked and would prevent any other thread from accessing the job queue ever again.