Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Process Synchronization in C/C++
Process synchronization is the technique to overcome the problem of concurrent access to shared data which can result in data inconsistency. A cooperating process is the one which can affect or be affected by other process which will lead to inconsistency in processes data therefore Process synchronization is required for consistency of data.
Syntax
/* General structure for process synchronization */
do {
entry_section();
critical_section();
exit_section();
remainder_section();
} while(1);
The Critical-Section Problem
Every process has a reserved segment of code which is known as Critical Section. In this section, process can change common variables, update tables, write files, etc. The key point to note about critical section is that when one process is executing in its critical section, no other process can execute in its critical section. Each process must request for permission before entering into its critical section and the section of a code implementing this request is the Entry Section, the end of the code is the Exit Section and the remaining code is the remainder section.
There are three requirements that must be satisfied for a critical section −
- Mutual Exclusion − If one process let's say P1 is executing in its critical section than any other process let's say P2 can't execute in its critical section.
- Progress − If there is no process executing in its critical section and there are processes who wants to enter in its critical section, then only those processes who are not executing in their remainder section can request to enter the critical section and the selection can be postponed indefinitely.
- Bounded Waiting − In bounded waiting, there are limits or bounds on the number of times a process can enter its critical section after a process has made a request to enter its critical section and before that request is granted.
Peterson's Solution
Peterson's solution is a classic software solution to the critical-section problem. It is restricted to two processes that alternate execution between their critical sections and remainder sections. Peterson's solution requires two data items to be shared between the two processes −
int turn;bool flag[2];
Here, variable turn indicates whose turn is to enter its critical section and flag array indicates whether the process is ready to enter its critical section.
Example: Peterson's Algorithm Implementation
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
/* Shared variables */
int turn = 0;
bool flag[2] = {false, false};
int shared_resource = 0;
void critical_section(int process_id) {
shared_resource++;
printf("Process %d in critical section, shared_resource = %d\n",
process_id, shared_resource);
}
void peterson_process(int i) {
int j = 1 - i; /* Other process */
/* Entry section */
flag[i] = true;
turn = j;
while (flag[j] && turn == j) {
/* Busy wait */
printf("Process %d waiting...\n", i);
sleep(1);
}
/* Critical section */
critical_section(i);
/* Exit section */
flag[i] = false;
printf("Process %d exited critical section\n", i);
}
int main() {
printf("Peterson's Algorithm Demonstration\n");
printf("Process 0 trying to enter critical section:\n");
peterson_process(0);
printf("\nProcess 1 trying to enter critical section:\n");
peterson_process(1);
return 0;
}
Peterson's Algorithm Demonstration Process 0 trying to enter critical section: Process 0 in critical section, shared_resource = 1 Process 0 exited critical section Process 1 trying to enter critical section: Process 1 in critical section, shared_resource = 2 Process 1 exited critical section
Semaphores
Semaphore is a synchronization tool that is used to overcome the problems generated by TestAndSet() and Swap() instructions. A semaphore S is an integer variable that can be accessed through two standard atomic operations that are wait() and signal() −
Semaphore Operations Syntax
wait(S) {
while (S <= 0)
; // no operation
S--;
}
signal(S) {
S++;
}
Example: Binary Semaphore Implementation
#include <stdio.h>
#include <stdbool.h>
typedef struct {
int value;
bool available;
} semaphore_t;
void init_semaphore(semaphore_t *sem, int initial_value) {
sem->value = initial_value;
sem->available = true;
}
void wait_semaphore(semaphore_t *sem) {
while (sem->value <= 0) {
printf("Waiting for semaphore...\n");
}
sem->value--;
printf("Semaphore acquired, value = %d\n", sem->value);
}
void signal_semaphore(semaphore_t *sem) {
sem->value++;
printf("Semaphore released, value = %d\n", sem->value);
}
int main() {
semaphore_t mutex;
init_semaphore(&mutex, 1); /* Binary semaphore */
printf("Initial semaphore value: %d\n", mutex.value);
/* Process 1 acquires semaphore */
printf("\nProcess 1 acquiring semaphore:\n");
wait_semaphore(&mutex);
/* Critical section simulation */
printf("Process 1 in critical section\n");
/* Process 1 releases semaphore */
printf("\nProcess 1 releasing semaphore:\n");
signal_semaphore(&mutex);
return 0;
}
Initial semaphore value: 1 Process 1 acquiring semaphore: Semaphore acquired, value = 0 Process 1 in critical section Process 1 releasing semaphore: Semaphore released, value = 1
Types of Semaphores
| Type | Value Range | Purpose | Example Use |
|---|---|---|---|
| Binary Semaphore | 0 or 1 | Mutual exclusion | Critical section protection |
| Counting Semaphore | 0 to n | Resource counting | Buffer pool management |
Conclusion
Process synchronization ensures data consistency in concurrent environments. Peterson's algorithm provides a software solution for two processes, while semaphores offer a more general hardware-assisted approach for multiple processes. Binary semaphores act as mutex locks for critical sections, while counting semaphores manage finite resources.
