Semaphore Example
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <unistd.h> //Header file for sleep(). man 3 sleep for details.
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
using namespace std;
sem_t mutex;
int sem_val = 1; /* Semaphore value 1 */
int sem_type = 1; /* 0 For threads, 1 for Process */
int counter = 0;
void *thread_handler(void *vargp)
{
sem_wait(&mutex);
counter++;
cout << "Job" << *(int *)vargp << " started, counter=" << counter << endl;
/* Run below program with/without sleep(1),
* when sleep is included, we need to have mutex
*/
sleep(1);
cout << "Job" << *(int *)vargp << " finished, counter=" << counter << endl;
sem_post(&mutex);
return NULL;
}
int main()
{
pthread_t thread_id[30];
int thread_arg[30];
/* Non recursive mutex */
if(sem_init(&mutex, sem_type, sem_val)) {
cout << "sem not initialized successfully" << endl;
}
printf("Before Thread\r\n");
for(int i = 0; i < 5; i++) {
thread_arg[i] = i;
pthread_create(&thread_id[i], NULL, thread_handler, (void *)&thread_arg[i]);
}
for(int i = 0; i < 5; i++) {
pthread_join(thread_id[i], NULL);
}
sem_destroy(&mutex);
return 0;
}
Implement your own Semaphore
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <condition_variable>
using namespace std;
#define THREAD_CNT 30
class semaphore {
private:
int m_value; // Value of semaphore.
pthread_mutex_t sync_mutex; // Controls access.
pthread_cond_t condition;; // Controls waiting and restart
public:
semaphore(int init): m_value(init) {
pthread_mutex_init(&sync_mutex, NULL);
pthread_cond_init(&condition, NULL);
}
~semaphore(){
pthread_mutex_destroy(&sync_mutex);
pthread_cond_destroy(&condition);
}
void down() {
pthread_mutex_lock(&sync_mutex);
// Check the mutex value, and wait if need be.
if(--m_value < 0) {
// Make us wait. When we wait, the mutex is unlocked until the
// wait ends.
pthread_cond_wait(&condition, &sync_mutex);
}
}
void up() {
// Start a waiting thread if required.
if(++m_value <= 0) {
pthread_cond_signal(&condition);
}
pthread_mutex_unlock(&sync_mutex);
}
};
semaphore sem(1);
int shared_resource = 0;
void *thread_handler(void *vargp)
{
sem.down();
shared_resource++;
std::cout << "Job" << *(int *)vargp << " started, shared_resource=" << shared_resource << endl << std::flush;
sleep(1);
std::cout << "Job" << *(int *)vargp << " finished, shared_resource=" << shared_resource << endl << std::flush;
sem.up();
return NULL;
}
int main()
{
pthread_t thread_id[THREAD_CNT];
int thread_arg[THREAD_CNT];
for(int i = 0; i < THREAD_CNT; i++) {
thread_arg[i] = i;
pthread_create(&thread_id[i], NULL, thread_handler, (void *)&thread_arg[i]);
}
for(int i = 0; i < THREAD_CNT; i++) {
pthread_join(thread_id[i], NULL);
}
return 0;
}