In this article, we will learn about all the synchronization problems that must be tested against every proposed synchronization technique. Synchronization problem arises when the execution of cooperating is not coordinated properly which may affect the result of execution.
Synchronization Problems
Producer-Consumer Problem
The producer-consumer problem is where the two cooperating processes share a common fixed-size buffer. Now, the scenario is that one of the processes is the producer process which produces an item to be placed in the buffer. And the other process is the consumer process which removes the item from the buffer and consumes it.
The synchronization problem emerges here when the production process has produced an item but the buffer is already full and cannot accommodate any new item. Or when the consumer process wants to consume an item but the buffer is empty and doesn’t have any item to be removed by the consumer.
Well, a solution to this problem we can make the producer process go to sleep till the buffer is full and should be awaked by the consumer process when it removes one item from the buffer. Similarly seeing buffer empty the consumer process must go to sleep and must be awakened only when the buffer place an item in the buffer.
This solution can be encoded in a simple C program as you can see below. You can notice we have a global variable count which would declare the number of items currently present in the buffer and the size of the buffer is N.
#define N 100
int count = 0;
void producer(void)
{
int item;
while (TRUE) {
item = produce item( );
if (count == N) sleep( );
inser t item(item);
count = count + 1;
if (count == 1) wakeup(consumer);
}
}
void consumer(void)
{
int item;
while (TRUE) {
if (count == 0) sleep( );
item = remove item( );
count = count −1;
if (count == N − 1) wakeup(producer);
consume item(item);
}
}
Using the global variable count the producer and consumer processes can easily check the status of the buffer. Accordingly, the producer process checks if the buffer is full the producer will go to sleep else it would add the item to the buffer and would increment the count.
The producer even checks if the buffer was empty before the addition of the item which would have let the consumer process go to sleep. So, it also gives a wake-up call to the consumer.
Similarly, the consumer process verifies if the buffer is empty then it will go to sleep, and if it not then it would remove one item from the buffer and consume it.
The consumer process would also check that before the removal of items from the buffer was the buffer full. If so, seeing this the producer might have gone to sleep then it also sends a wake-up call to the producer process.
Readers Writers Synchronization Problem
To understand the readers-writer’s problem, consider a scenario that there is a database that has to share by several concurrent processes. Now there may be some processes that only want to read the database and don’t want to perform any changes. But there may be some processes that want to perform some updation too.
These processes can be classified into two types. The processes that only want to read the database and won’t do any changes to the database can be classified as readers process. The processes that want to read as well as write the database and will perform some update are classified as writers process.
The synchronization problem arises when a writer process and other processes (may it be reader or writer) try to access the database simultaneously this is termed as the readers-writers problem. Though many readers can access the shared database simultaneously. To overcome this problem the writer process must always access the shared database exclusively.
The solution to the synchronization problem above can be understood as
- If a reader has obtained access to the shared database no writer must be allowed to access the database.
- If a writer has obtained access to the shared database no reader must be allowed to access the database.
- No two writers must access the shared database simultaneously.
The code below verifies all three solutions we discussed above for the readers-writers problem.
Int readcount=0
Semaphore mutex=1;
Semaphore wrt=1;
Void Reader(void){
While(true)
{
Down(mutex);
readcount ++;
if (readcount ==1) down(wrt),
up(mutex);
// access database
//Exit Code
Down(mutex)
Readcount –;
If(readcount ==0) up(wrt);
Up(mutex);
//process data
}
}
Void writer(void){
While (true){
Down(wrt);
//access database
Up(wrt);
}
Dining Philosophers Synchronization Problem
To understand the dining philosopher’s problem, consider the scenario that there are five philosophers who are sitting around a circular table. Their only work is to think and eat.
At the center of the table, there is a rice bowl and there is only one chopstick between two neighboring philosophers. Timely each philosopher gets hungry. To start eating the philosopher must hold both the chopsticks but it can pick only one chopstick at a time thereby holding the chopsticks one by one. Once the philosopher has stopped eating it will release both the chopstick and start thinking.
The problem is that if two adjacent philosophers try to eat at the same time, they may get blocked forever and may lead to the race condition. To avoid this each chopstick is represented using semaphore. To grab the left and right chopstick we must use down() operation and to release the chopstick use up() operation.
semaphore chopstick[5];
do {
down(chopstick[i]);
down(chopstick[(i+l) % 5]);
//eat
up(chopstick[i]);
up(chopstick[(i+l) % 5]);
// think
} while (TRUE);
With this structure, we can restrict two neighbors from trying to eat at the same time.
These three synchronization problems must be checked whenever a new synchronization scheme is introduced to ensure that the new scheme does not lead to any race condition or deadlock during process synchronization.