Semaphores In C
Process synchronisation and multithreading both benefit greatly from the data management mechanism known as semaphore.
- The use of semaphore in the C programming language will be examined in this article.
- Within Linux systems, there is a POSIX semaphore library. In this instance, we will apply this Semaphores concept.
- The fundamental code of a semaphore cannot be entered directly into client code since it needs to be atomic, and doing so would cause a context switch and unexpected outcomes.
The built-in semaphore library of the POSIX system in Linux is available. In order to use, it requires that we:
- Put the header file semaphore.h in
- Link the code together using the -lpthread -lrt option.
Sem_init():
- When a semaphore at "s" already exists but is unidentified, a new semaphore will be generated; otherwise, the current semaphore will be deleted.
- In this method, "s" denotes a newly created Semaphore instance, and "shared" denotes a signal or pennant that denotes whether the semaphore can be distributed using the forked() function or not.
- The set starting point of the semaphore is the input value.
Sem_wait():
- The sem_wait() method holds a semaphore by performing a semaphore lock action on the semaphore that is given by "s".
- To keep a semaphore or allow it wait in queue, use the sem-wait technique. When another process calls sem_post(), some of the already overloaded processes start to run again.
- The sem_wait function can be used to lock a particular semaphore:
int sem_wait(sem_t *sem);
Sem_post():
- Whenever sem post is called, the value increases and one of the backed up or awaiting actions begins to run, unlocking the semaphore that has already been locked.
- The sem_post function is used to indicate or release a semaphore:
int sem_post(sem_t *sem);
Initiating a semaphore with sem_init (for both the processes or for the threads) or sem_open (for interprocess communication) will allow to do so.
sem_init(sem_t *sem, int pshared, unsigned int values);
sem: specifies the semaphore that has to be initialised.
pshared: The freshly initialised semaphore is either shared between processes or between threads, depending on the value of the pshared argument.
A number other than zero indicates that the semaphore is shared between processes, while a value of zero indicates that it is shared between threads.
values: Indicates the value to be put into the freshly initialised semaphore.
Sem_destory():
- Using the sem destroy() function, an unnamed semaphore "s" that has been initialised is destroyed.
- By utilising the sem_destroy keyword, we can eliminate a semaphore:
sem_destroy(sem_t *mutex);
The data type sem_t is used to declare a semaphore.
Semaphore Initialization With the Intraprocess Scope:
The semaphore can only be used by all of the threads in this process when pshared is 0.
#include <semaphore.h>
sem_t sem;
int temp;
int count_var = 4;
// only to be used in this process //
temp = sem_init(&sem, 0, count_var);
Semaphore Initialization With the Interprocess Scope:
The semaphore may be shared by additional processes if pshared is nonzero.
#include <semaphore.h>
sem_t sem;
int temp;
int count_var = 4;
// to be shared by all processes //
temp = sem_init(&sem, 1, count_var);
C Program for implementing the semaphores:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_t mutex;
void* thread(void* arg)
{
// wait
sem_wait(&mutex);
printf("\nEntered the thread....\n");
// critical section
sleep(4);
// signal
printf("\n Exit the thread....\n");
sem_post(&mutex);
}
int main()
{
sem_init(&mutex, 0, 1);
pthread_t t11,t22;
pthread_create(&t11,NULL,thread,NULL);
sleep(2);
pthread_create(&t22,NULL,thread,NULL);
pthread_join(t11,NULL);
pthread_join(t22,NULL);
sem_destroy(&mutex);
return 0;
}
OUTPUT:
![Semaphores In C](https://static.tutorialandexample.com/c/semaphores-in-c1.png)
Explanation:
- One thread starts 2 seconds after the other, and so on.
- 4 seconds will pass after the first thread gets the lock before going to sleep.
- As a result, the second thread won't start right away after it is called; instead, it will start 4 - 2 = 2 seconds later.
The output would have been the following as a result of context switching if semaphore had not been used:
![Semaphores In C](https://static.tutorialandexample.com/c/semaphores-in-c2.png)
Advantages of Semaphores:
- In the critical region, semaphores only let one process to completion.
- There is no resource waste from busy waiting in semaphores since processor time is not wasted verifying if a condition is met to allow a process to access the important region.
- The machine-independent microkernel code uses semaphores as its primary data structure. They therefore don't depend on machines.
Disadvantages of Semaphores:
- Due to the complexity of semaphores, it is essential to implement the wait and signal actions in the proper sequence in order to avoid deadlocks.
- As a result of semaphores, high priority processes may enter the crucial section last and low priority processes sooner.