A semaphore is simple enough (from wikipedia):
In computer science, particularly in operating systems, a semaphore is a variable or abstract data type that is used for controlling access, by multiple processes, to a common resource in a parallel programming or a multi user environment.
More or less semaphores C++11 are used for is keeping track of how many resources are currently available for use at a given time. This usually (almost always) applies to how many threads are currently available to the operating system. However, I have heard the term used in several instances when referring to memory, I do not know if this is the correct usage or not.
More straight forward a semaphore is simply a counter, used to keep track of how many of a particular resource you have available. If for example, we would like to use a semaphore to print the thread number, we would do something like below (represented visually):
A special case of the semaphore is a mutex. A mutex is more or less a binary semaphore which is used to lock/unlock a critical section of code, meaning only one thread can access it at a given time (without causing issues). POSIX, which stands for: “Portable Operating System Interface,” has a semaphore C library for ease of use. However, if you are using a Semaphore I recommend using the standard libraries since they are fairly easy to read. Below is an example (also viewable on my github) using semaphores c++11:
Output of Semaphores C++11:
Running 15 in parallel using Semaphores C++11:
Thread: 1 / 15 current count is: 1
Thread: 2 / 15 current count is: 2
Thread: 3 / 15 current count is: 3
Thread: 4 / 15 current count is: 4
Thread: 5 / 15 current count is: 5
Thread: 6 / 15 current count is: 6
Thread: 7 / 15 current count is: 7
Thread: 8 / 15 current count is: 8
Thread: 9 / 15 current count is: 9
Thread: 10 / 15 current count is: 10
Thread: 11 / 15 current count is: 11
Thread: 12 / 15 current count is: 12
Thread: 13 / 15 current count is: 13
Thread: 14 / 15 current count is: 14
Thread: 15 / 15 current count is: 15
Completed semaphore C++11 example!
It is fairly clear there could have been a race condition, however with the use of the following lines:
while(num != current || !ready){ cv.wait(lck); } current++;
We only allowed the thread who’s number matched the variable “current” to run. This enabled the threads to be printed in order with the use of semaphores C++11!
The code above, using semaphores c++11 is much nicer and easier than using the POSIX library, but it is about as easy (just far less readable) to use POSIX. If you are interested in using a POSIX library (or are not able to use Semaphores C++11) I am not going to supply an example, but I recommend checking out the open group or here. The design pattern will be the same as the Semaphores C++11 example, it will just be slightly harder to read.
fwiw, this seg faults for me.
Compiled on RHEL 6.5. Tried using both GCC 4.4.7 and 4.7.0.
I do not know your exact problem, but I am guessing it’s the C++11 syntax[1]. C++11 is not fully supported in gcc 4.4.7 really and gcc 4.7 only has some support[2], but concurrency is an issue.
Hi Austin,
Really good explanation. I have some queries,
Once “threads[id] = std::thread(print_num, id, threadnum);” code get executed then print_num function get call 15 times and all this function not processed further because of cv.wait(lck); I think all this thread goes into waiting state.(Please clear if I am wrong.)
But Once run() function gets executes then all threads executed once -bye – one on their creation order.
My question is that If all that If all thread was in waiting state and once run get execute then how this thread run sequentially. Because all in waiting state , So any thread could start randomly ?
Please help me to clear my concepts.
Thanks,
Vijay
We are using a Semaphore which is a mutex with a count (basically): https://austingwalters.com/mutex-process-synchronization/
They run sequentially because the semphore only releases them in the order of creation (1, 2, 3, 4, …, etc.).
That’s what makes semaphores special, the semaphore only “unlocks” the thread on their turn.
After run() is called, all threads got notification and each thread’s condition variable tried to lock mutex then went to check while condition but except for num == 0 thread all other thread passed the while condition and again went inside while so, again started waiting.
num == 0 thread didn’t pass while condition so it printed and incremented current and notified all condition variable. Now num == 1 matched current == 1 so that thread while condition check and printed, notified and so on… In this way all the threads printed sequencely.