A Barrier in computing is a synchronization method where a group of threads cannot proceed until a condition allows the blocked threads to proceed. In this post we will construe an example of a Barrier that relates to men and women at the dinner table using pthreads. We will have a bunch of men waiting to get their food, but the men will be blocked until the woman has eaten, thus, trigger the start state of the Barrier.
Barrier Pthread Example: Ladies First!
Let’s outline the following case for our Barrier. Ladies are first so all the men must wait until the woman has eaten.
- We have 2 men pthreads and 1 woman pthread
- The men will wait until the woman has eaten - implicitly the men pthreads must start before the woman
- Once the woman has eaten the men are free to eat
- Men will eat and the program will end
Relation of the Barrier Example in pthreads
Since a Barrier needs synchronization and in pthreads the fundamental building block for synchronization is the mutex. We will use the mutex for our example. We will also use another tool in the pthread library called the condition variable.
Distinction between a pthread Mutex and Condition variable
The mutex in the pthread library lets a thread synchronize on data. The mutex will block while a thread works on data. The condition variable is a step further where it allows threads to synchornize on the value of the data. Think of them as a one-to-many relationship - for a single mutex you could have mutiple condition variables. For the purposes of this exercise we’ll have one mutex which relates to a single condition variable. Having the same condition variable map to multiple mutex variables wouldn’t be good. I’ll quote the
pthread_cond_wait man pages. “The effect of using more than one mutex for concurrent
pthread_cond_timedwait() operations on the same condition variable is undefined; that is, a condition variable becomes bound to a unique mutex when a thread waits on the condition variable, and this (dynamic) binding ends when the wait returns.”
Relating the Barrier Example to - Ladies First
In the Ladies First Barrier example we have the following synchronization details:
- 2 pthreads for the men, 1 pthread for the woman
- The men pthreads will have to go first - more on this later
- The men will wait on a condition variable called
- The woman, once done eating will broadcast to all men waiting on the condition variable
- Underlying this will be a mutex called
Ladies First Barrier Example in C using Pthreads
We’ve gotten a lot of background already, at this point let’s get straight to our example in c using pthreads.
When this program is run the following output was captured. These are pthreads so we cannot guarantee execution order can be different each time the program is run.
From the output above we can see the the 2 men pthreads will obtain the food mutex and then wait on the condition variable. The delay happens and then the woman comes in and get’s the food mutex right away. She then broadcasts out to all the men pthreads waiting on the food mutex and they get to eat. Pay some close attention to the mutex and how they are locked and unlocked.
The finer details of this Barrier example
There are a couple of fine points to be made here in this Barrier example.
The first and biggest to me is not a fine detail, but a major detail. When the thread hits the
pthread_cond_wait() function which MUST take a locked mutex AND a condition variable, something special happens. What happens is the mutex is the mutex is released. This can be seen in the output section of the example where the men pthreads get the food mutex and then wait for the condition. The man #2 and #1 both are waiting on the condition and from the print’s above are passed the mutex without it being unlocked. See the
pthread_cond_wait man pages for more on this.
The second point to be made is the sleep we’ve inserted. This is needed because we need the mean blocked on the condition variable before the woman broadcasts to them. This functionality is for the example and is quite crude.
Where to go from here
If this example is useful please say so in the comments below! This code could be much more robust by actually checking return codes from the pthread library calls which set the error number. The sleep call is crude. In a real world scenario we’d need to consider signals which adds another layer of complexity.
The last part is we don’t consider destroying our mutex and condition variable.