In this recipe, we'll create a multi-threaded program to increment an integer until it reaches 200000. Again, the code section that takes care of the increments must be protected and we'll use POSIX semaphores. The main method will create the two threads and ensure that the resources are destroyed correctly. Let's get started:
- Let's open a new file called posixSemaphore.cpp and develop the structure and the critical section method:
#include <pthread.h>
#include <semaphore.h>
#include <iostream>
struct ThreadInfo
{
sem_t sem;
int counter;
};
void* increment(void *arg)
{
ThreadInfo* info = static_cast<ThreadInfo*>(arg);
sem_wait(&info->sem);
std::cout << "Thread Started ... " << std::endl;
for (int i = 0; i < 100000; ++i)
info->counter++;
std::cout << "Thread Finished ... " << std::endl;
sem_post(&info->sem);
return nullptr;
}
- Now, in the main section, add the init method for the lock that's needed for the synchronization between threads:
int main()
{
ThreadInfo thInfo;
thInfo.counter = 0;
if (sem_init(&thInfo.sem, 0, 1) != 0)
{
std::cout << "sem_init failed!" << std::endl;
return 1;
}
- Now that the init section is complete, let's write the code that will start the two threads:
pthread_t t1;
if (pthread_create(&t1, nullptr, &increment, &thInfo) != 0)
{
std::cout << "pthread_create for t1 failed! " << std::endl;
return 2;
}
pthread_t t2;
if (pthread_create(&t2, nullptr, &increment, &thInfo) != 0)
{
std::cout << "pthread_create for t2 failed! " << std::endl;
return 3;
}
- Finally, here's the closing part:
pthread_join(t1, nullptr);
pthread_join(t2, nullptr);
std::cout << "posixSemaphore:: Threads elaboration
finished. Counter = "
<< thInfo.counter << std::endl;
sem_destroy(&thInfo.sem);
return 0;
}
The same program we used for POSIX mutexes now runs with POSIX semaphores. As you can see, the program's design doesn't change – what really changes is the APIs we used to protect the critical section.