Semaphore
Introduction#
Semaphores are not available in C++ as of now, but can easily be implemented with a mutex and a condition variable.
This example was taken from:
https://stackoverflow.com/questions/4792449/c0x-has-no-semaphores-how-to-synchronize-threads
Semaphore C++ 11
#include <mutex>
#include <condition_variable>
class Semaphore {
public:
Semaphore (int count_ = 0)
: count(count_)
{
}
inline void notify( int tid ) {
std::unique_lock<std::mutex> lock(mtx);
count++;
cout << "thread " << tid << " notify" << endl;
//notify the waiting thread
cv.notify_one();
}
inline void wait( int tid ) {
std::unique_lock<std::mutex> lock(mtx);
while(count == 0) {
cout << "thread " << tid << " wait" << endl;
//wait on the mutex until notify is called
cv.wait(lock);
cout << "thread " << tid << " run" << endl;
}
count--;
}
private:
std::mutex mtx;
std::condition_variable cv;
int count;
};
Semaphore class in action
The following function adds four threads. Three threads compete for the semaphore, which is set to a count of one. A slower thread calls notify_one()
, allowing one of the waiting threads to proceed.
The result is that s1
immediately starts spinning, causing the Semaphore’s usage count
to remain below 1. The other threads wait in turn on the condition variable until notify() is called.
int main()
{
Semaphore sem(1);
thread s1([&]() {
while(true) {
this_thread::sleep_for(std::chrono::seconds(5));
sem.wait( 1 );
}
});
thread s2([&]() {
while(true){
sem.wait( 2 );
}
});
thread s3([&]() {
while(true) {
this_thread::sleep_for(std::chrono::milliseconds(600));
sem.wait( 3 );
}
});
thread s4([&]() {
while(true) {
this_thread::sleep_for(std::chrono::seconds(5));
sem.notify( 4 );
}
});
s1.join();
s2.join();
s3.join();
s4.join();
...
}