# Peterson’s Algorithm in Process Synchronization

Last Updated : 08 Apr, 2024

Prerequisite – Synchronization, Critical SectionÂ

The producer-consumer problem (or bounded buffer problem) describes two processes, the producer and the consumer, which share a common, fixed-size buffer used as a queue. Producers produce an item and put it into the buffer. If the buffer is already full then the producer will have to wait for an empty block in the buffer. Consumers consume an item from the buffer. If the buffer is already empty then the consumer will have to wait for an item in the buffer. Implement Peterson’s Algorithm for the two processes using shared memory such that there is mutual exclusion between them. The solution should have free from synchronization problems.Â

Peterson’s algorithm –

C++ ```#include <iostream> #include <thread> #include <vector> const int N = 2; // Number of threads (producer and consumer) std::vector<bool> flag(N, false); // Flags to indicate readiness int turn = 0; // Variable to indicate turn void producer(int j) { do { flag[j] = true; // Producer j is ready to produce turn = 1 - j; // Allow consumer to consume while (flag[1 - j] && turn == 1 - j) { // Wait for consumer to finish // Producer waits if consumer is ready and it's consumer's turn } // Critical Section: Producer produces an item and puts it into the buffer flag[j] = false; // Producer is out of the critical section // Remainder Section: Additional actions after critical section } while (true); // Continue indefinitely } void consumer(int i) { do { flag[i] = true; // Consumer i is ready to consume turn = i; // Allow producer to produce while (flag[1 - i] && turn == i) { // Wait for producer to finish // Consumer waits if producer is ready and it's producer's turn } // Critical Section: Consumer consumes an item from the buffer flag[i] = false; // Consumer is out of the critical section // Remainder Section: Additional actions after critical section } while (true); // Continue indefinitely } int main() { std::thread producerThread(producer, 0); // Create producer thread std::thread consumerThread(consumer, 1); // Create consumer thread producerThread.join(); // Wait for producer thread to finish consumerThread.join(); // Wait for consumer thread to finish return 0; } ``` C ```// code for producer (j) // producer j is ready // to produce an item flag[j] = true; // but consumer (i) can consume an item turn = i; // if consumer is ready to consume an item // and if its consumer's turn while (flag[i] == true &amp;&amp; turn == i) { /* then producer will wait*/ } // otherwise producer will produce // an item and put it into buffer (critical Section) // Now, producer is out of critical section flag[j] = false; // end of code for producer //-------------------------------------------------------- // code for consumer i // consumer i is ready // to consume an item flag[i] = true; // but producer (j) can produce an item turn = j; // if producer is ready to produce an item // and if its producer's turn while (flag[j] == true &amp;&amp; turn == j) { /* then consumer will wait */ } // otherwise consumer will consume // an item from buffer (critical Section) // Now, consumer is out of critical section flag[i] = false; // end of code for consumer ``` Java ```import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Main { static final int N = 2; // Number of threads (producer and consumer) static final Lock lock = new ReentrantLock(); static final Condition[] readyToProduce = {lock.newCondition(), lock.newCondition()}; static volatile int turn = 0; // Variable to indicate turn static void producer(int j) { do { lock.lock(); try { while (turn != j) { readyToProduce[j].await(); } // Critical Section: Producer produces an item and puts it into the buffer System.out.println("Producer " + j + " produces an item."); turn = 1 - j; // Allow consumer to consume readyToProduce[1 - j].signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } // Remainder Section: Additional actions after critical section } while (true); // Continue indefinitely } static void consumer(int i) { do { lock.lock(); try { while (turn != i) { readyToProduce[i].await(); } // Critical Section: Consumer consumes an item from the buffer System.out.println("Consumer " + i + " consumes an item."); turn = 1 - i; // Allow producer to produce readyToProduce[1 - i].signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } // Remainder Section: Additional actions after critical section } while (true); // Continue indefinitely } public static void main(String[] args) { Thread producerThread = new Thread(() -> producer(0)); // Create producer thread Thread consumerThread = new Thread(() -> consumer(1)); // Create consumer thread producerThread.start(); // Start producer thread consumerThread.start(); // Start consumer thread try { Thread.sleep(1000); // Run for 1 second } catch (InterruptedException e) { e.printStackTrace(); } finally { producerThread.interrupt(); // Interrupt producer thread consumerThread.interrupt(); // Interrupt consumer thread } } } ``` Python3 ```import threading N = 2 # Number of threads (producer and consumer) flag = [False] * N # Flags to indicate readiness turn = 0 # Variable to indicate turn # Function for producer thread def producer(j): while True: flag[j] = True # Producer j is ready to produce turn = 1 - j # Allow consumer to consume while flag[1 - j] and turn == 1 - j: # Wait for consumer to finish # Producer waits if consumer is ready and it's consumer's turn pass # Critical Section: Producer produces an item and puts it into the buffer flag[j] = False # Producer is out of the critical section # Remainder Section: Additional actions after critical section # Function for consumer thread def consumer(i): while True: flag[i] = True # Consumer i is ready to consume turn = i # Allow producer to produce while flag[1 - i] and turn == i: # Wait for producer to finish # Consumer waits if producer is ready and it's producer's turn pass # Critical Section: Consumer consumes an item from the buffer flag[i] = False # Consumer is out of the critical section # Remainder Section: Additional actions after critical section # Create producer and consumer threads producer_thread = threading.Thread(target=producer, args=(0,)) consumer_thread = threading.Thread(target=consumer, args=(1,)) # Start the threads producer_thread.start() consumer_thread.start() # Wait for the threads to finish producer_thread.join() consumer_thread.join() ``` C# ```using System; using System.Threading; using System.Collections.Generic; class GFG { const int N = 2; // Number of threads static List<bool> flag = new List<bool>(new bool[N]); static int turn = 0; // Variable to indicate turn // Producer method static void Producer(object obj) { int j = (int)obj; do { flag[j] = true; turn = 1 - j; // Wait for consumer to finish // Producer waits if consumer is ready and it's consumer's turn while (flag[1 - j] && turn == 1 - j) { // Wait } // Critical Section: Producer produces an item and // puts it into the buffer Console.WriteLine(\$"Producer {j} produced an item"); flag[j] = false; // Remainder Section: Additional actions after critical section Thread.Sleep(1000); } while (true); } // Consumer method static void Consumer(object obj) { int i = (int)obj; do { flag[i] = true; turn = i; // Wait for producer to finish // Consumer waits if producer is ready and it's producer's turn while (flag[1 - i] && turn == i) { // Wait } // Critical Section: Consumer consumes an item from buffer Console.WriteLine(\$"Consumer {i} consumed an item"); flag[i] = false; // Remainder Section: Additional actions after critical section Thread.Sleep(1000); } while (true); } static void Main(string[] args) { Thread producerThread = new Thread(Producer); // Create producer thread Thread consumerThread = new Thread(Consumer); // Create consumer thread producerThread.Start(0); // Start producer thread with index 0 consumerThread.Start(1); // Start consumer thread with index 1 producerThread.Join(); // Wait for producer thread to finish consumerThread.Join(); // Wait for consumer thread to finish } } ``` JavaScript ```const N = 2; // Number of threads (producer and consumer) const lockObject = {}; // Lock object for synchronization async function producer(j) { while (true) { await new Promise((resolve) => { lock(lockObject, () => { // Critical Section: Producer produces an item and puts it into the buffer console.log(`Producer \${j} produces an item`); // Remainder Section: Additional actions after the critical section }); resolve(); }); await sleep(100); // Simulate some work before the next iteration } } async function consumer(i) { while (true) { await new Promise((resolve) => { lock(lockObject, () => { // Critical Section: Consumer consumes an item from the buffer console.log(`Consumer \${i} consumes an item`); // Remainder Section: Additional actions after the critical section }); resolve(); }); await sleep(100); // Simulate some work before the next iteration } } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function lock(obj, callback) { if (!obj.__lock__) { obj.__lock__ = true; try { callback(); } finally { delete obj.__lock__; } } } // Start producer and consumer threads producer(0); // Start producer 0 producer(1); // Start producer 1 consumer(0); // Start consumer 0 consumer(1); // Start consumer 1 // Run for 1 second setTimeout(() => { process.exit(); // Terminate the program after 1 second }, 1000); ```

### Explanation of Peterson’s AlgorithmÂ

Peterson’s Algorithm is used to synchronize two processes. It uses two variables, a bool array flag of size 2 and an int variable turn to accomplish it. In the solution, i represents the Consumer and j represents the Producer. Initially, the flags are false. When a process wants to execute it’s critical section, it sets its flag to true and turn into the index of the other process. This means that the process wants to execute but it will allow the other process to run first. The process performs busy waiting until the other process has finished it’s own critical section. After this, the current process enters its critical section and adds or removes a random number from the shared buffer. After completing the critical section, it sets it’s own flag to false, indicating it does not wish to execute anymore. The program runs for a fixed amount of time before exiting. This time can be changed by changing value of the macro RT.Â

C++ ```#include <iostream> #include <vector> #ifdef _WIN32 #include <windows.h> #else #include <unistd.h> #endif #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/time.h> #define BSIZE 8 #define PWT 2 #define CWT 10 #define RT 10 int shmid1, shmid2, shmid3, shmid4; key_t k1 = 5491, k2 = 5812, k3 = 4327, k4 = 3213; bool* SHM1; int* SHM2; int* SHM3; void initializeBuffer(int* buf, int size) { for (int i = 0; i < size; ++i) { buf[i] = 0; } } int myrand(int n) { static int initialized = 0; if (!initialized) { srand(static_cast<unsigned>(time(nullptr))); initialized = 1; } return (rand() % n + 1); } void cleanup() { shmdt(SHM1); shmdt(SHM2); shmdt(SHM3); shmctl(shmid1, IPC_RMID, nullptr); shmctl(shmid2, IPC_RMID, nullptr); shmctl(shmid3, IPC_RMID, nullptr); shmctl(shmid4, IPC_RMID, nullptr); } int main() { shmid1 = shmget(k1, sizeof(bool) * 2, IPC_CREAT | 0660); shmid2 = shmget(k2, sizeof(int) * 1, IPC_CREAT | 0660); shmid3 = shmget(k3, sizeof(int) * BSIZE, IPC_CREAT | 0660); shmid4 = shmget(k4, sizeof(int) * 1, IPC_CREAT | 0660); if (shmid1 < 0 || shmid2 < 0 || shmid3 < 0 || shmid4 < 0) { perror("Main shmget error: "); exit(1); } SHM3 = static_cast<int*>(shmat(shmid3, nullptr, 0)); initializeBuffer(SHM3, BSIZE); struct timeval t; gettimeofday(&t, nullptr); time_t t1 = t.tv_sec; int* state = static_cast<int*>(shmat(shmid4, nullptr, 0)); *state = 1; int wait_time; int i = 0; // Consumer int j = 1; // Producer if (fork() == 0) // Producer code { SHM1 = static_cast<bool*>(shmat(shmid1, nullptr, 0)); SHM2 = static_cast<int*>(shmat(shmid2, nullptr, 0)); SHM3 = static_cast<int*>(shmat(shmid3, nullptr, 0)); if (SHM1 == nullptr || SHM2 == nullptr || SHM3 == nullptr) { perror("Producer shmat error: "); exit(1); } bool* flag = SHM1; int* turn = SHM2; int* buf = SHM3; int index = 0; while (*state == 1) { flag[j] = true; printf("Producer is ready now.\n\n"); *turn = i; while (flag[i] == true && *turn == i); // Critical Section Begin index = 0; while (index < BSIZE) { if (buf[index] == 0) { int tempo = myrand(BSIZE * 3); printf("Job %d has been produced\n", tempo); buf[index] = tempo; break; } index++; } if (index == BSIZE) printf("Buffer is full, nothing can be produced!!!\n"); printf("Buffer: "); index = 0; while (index < BSIZE) printf("%d ", buf[index++]); printf("\n"); // Critical Section End flag[j] = false; if (*state == 0) break; wait_time = myrand(PWT); printf("Producer will wait for %d seconds\n\n", wait_time); #ifdef _WIN32 Sleep(wait_time * 1000); #else usleep(wait_time * 1000000); #endif } exit(0); } if (fork() == 0) // Consumer code { SHM1 = static_cast<bool*>(shmat(shmid1, nullptr, 0)); SHM2 = static_cast<int*>(shmat(shmid2, nullptr, 0)); SHM3 = static_cast<int*>(shmat(shmid3, nullptr, 0)); if (SHM1 == nullptr || SHM2 == nullptr || SHM3 == nullptr) { perror("Consumer shmat error:"); exit(1); } bool* flag = SHM1; int* turn = SHM2; int* buf = SHM3; int index = 0; flag[i] = false; while (*state == 1) { flag[i] = true; printf("Consumer is ready now.\n\n"); *turn = j; while (flag[j] == true && *turn == j); // Critical Section Begin if (buf[0] != 0) { printf("Job %d has been consumed\n", buf[0]); buf[0] = 0; index = 1; while (index < BSIZE) { buf[index - 1] = buf[index]; index++; } buf[index - 1] = 0; } else printf("Buffer is empty, nothing can be consumed!!!\n"); printf("Buffer: "); index = 0; while (index < BSIZE) printf("%d ", buf[index++]); printf("\n"); // Critical Section End flag[i] = false; if (*state == 0) break; wait_time = myrand(CWT); printf("Consumer will sleep for %d seconds\n\n", wait_time); #ifdef _WIN32 Sleep(wait_time * 1000); #else usleep(wait_time * 1000000); #endif } exit(0); } // Parent process will now wait for RT seconds before causing the child to terminate while (1) { gettimeofday(&t, nullptr); time_t t2 = t.tv_sec; if (t2 - t1 > RT) { *state = 0; break; } } // Waiting for both processes to exit wait(nullptr); wait(nullptr); cleanup(); printf("The clock ran out.\n"); return 0; } ``` C ```// C program to implement Petersonâ€™s Algorithm // for producer-consumer problem. #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;unistd.h&gt; #include &lt;time.h&gt; #include &lt;sys/types.h&gt; #include &lt;sys/ipc.h&gt; #include &lt;sys/shm.h&gt; #include &lt;stdbool.h&gt; #define _BSD_SOURCE #include &lt;sys/time.h&gt; #define BSIZE 8 // Buffer size #define PWT 2 // Producer wait time limit #define CWT 10 // Consumer wait time limit #define RT 10 // Program run-time in seconds int shmid1, shmid2, shmid3, shmid4; key_t k1 = 5491, k2 = 5812, k3 = 4327, k4 = 3213; bool* SHM1; int* SHM2; int* SHM3; int myrand(int n) // Returns a random number between 1 and n { time_t t; srand((unsigned)time(&amp;t)); return (rand() % n + 1); } int main() { shmid1 = shmget(k1, sizeof(bool) * 2, IPC_CREAT | 0660); // flag shmid2 = shmget(k2, sizeof(int) * 1, IPC_CREAT | 0660); // turn shmid3 = shmget(k3, sizeof(int) * BSIZE, IPC_CREAT | 0660); // buffer shmid4 = shmget(k4, sizeof(int) * 1, IPC_CREAT | 0660); // time stamp if (shmid1 &lt; 0 || shmid2 &lt; 0 || shmid3 &lt; 0 || shmid4 &lt; 0) { perror(&quot;Main shmget error: &quot;); exit(1); } SHM3 = (int*)shmat(shmid3, NULL, 0); int ix = 0; while (ix &lt; BSIZE) // Initializing buffer SHM3[ix++] = 0; struct timeval t; time_t t1, t2; gettimeofday(&amp;t, NULL); t1 = t.tv_sec; int* state = (int*)shmat(shmid4, NULL, 0); *state = 1; int wait_time; int i = 0; // Consumer int j = 1; // Producer if (fork() == 0) // Producer code { SHM1 = (bool*)shmat(shmid1, NULL, 0); SHM2 = (int*)shmat(shmid2, NULL, 0); SHM3 = (int*)shmat(shmid3, NULL, 0); if (SHM1 == (bool*)-1 || SHM2 == (int*)-1 || SHM3 == (int*)-1) { perror(&quot;Producer shmat error: &quot;); exit(1); } bool* flag = SHM1; int* turn = SHM2; int* buf = SHM3; int index = 0; while (*state == 1) { flag[j] = true; printf(&quot;Producer is ready now.\n\n&quot;); *turn = i; while (flag[i] == true &amp;&amp; *turn == i) ; // Critical Section Begin index = 0; while (index &lt; BSIZE) { if (buf[index] == 0) { int tempo = myrand(BSIZE * 3); printf(&quot;Job %d has been produced\n&quot;, tempo); buf[index] = tempo; break; } index++; } if (index == BSIZE) printf(&quot;Buffer is full, nothing can be produced!!!\n&quot;); printf(&quot;Buffer: &quot;); index = 0; while (index &lt; BSIZE) printf(&quot;%d &quot;, buf[index++]); printf(&quot;\n&quot;); // Critical Section End flag[j] = false; if (*state == 0) break; wait_time = myrand(PWT); printf(&quot;Producer will wait for %d seconds\n\n&quot;, wait_time); sleep(wait_time); } exit(0); } if (fork() == 0) // Consumer code { SHM1 = (bool*)shmat(shmid1, NULL, 0); SHM2 = (int*)shmat(shmid2, NULL, 0); SHM3 = (int*)shmat(shmid3, NULL, 0); if (SHM1 == (bool*)-1 || SHM2 == (int*)-1 || SHM3 == (int*)-1) { perror(&quot;Consumer shmat error:&quot;); exit(1); } bool* flag = SHM1; int* turn = SHM2; int* buf = SHM3; int index = 0; flag[i] = false; sleep(5); while (*state == 1) { flag[i] = true; printf(&quot;Consumer is ready now.\n\n&quot;); *turn = j; while (flag[j] == true &amp;&amp; *turn == j) ; // Critical Section Begin if (buf[0] != 0) { printf(&quot;Job %d has been consumed\n&quot;, buf[0]); buf[0] = 0; index = 1; while (index &lt; BSIZE) // Shifting remaining jobs forward { buf[index - 1] = buf[index]; index++; } buf[index - 1] = 0; } else printf(&quot;Buffer is empty, nothing can be consumed!!!\n&quot;); printf(&quot;Buffer: &quot;); index = 0; while (index &lt; BSIZE) printf(&quot;%d &quot;, buf[index++]); printf(&quot;\n&quot;); // Critical Section End flag[i] = false; if (*state == 0) break; wait_time = myrand(CWT); printf(&quot;Consumer will sleep for %d seconds\n\n&quot;, wait_time); sleep(wait_time); } exit(0); } // Parent process will now for RT seconds before causing child to terminate while (1) { gettimeofday(&amp;t, NULL); t2 = t.tv_sec; if (t2 - t1 &gt; RT) // Program will exit after RT seconds { *state = 0; break; } } // Waiting for both processes to exit wait(); wait(); printf(&quot;The clock ran out.\n&quot;); return 0; } ``` Java ```class PetersonsAlgorithm { static final int BUFFER_SIZE = 8; static volatile boolean[] flag = new boolean[2]; static volatile int turn; static volatile int[] buffer = new int[BUFFER_SIZE]; static class Producer extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { flag[0] = true; turn = 1; while (flag[1] && turn == 1) ; int job = (int) (Math.random() * 30) + 1; System.out.println("Producer is ready now."); System.out.println("Job " + job + " has been produced"); // Critical Section: Add to buffer for (int j = 0; j < BUFFER_SIZE; j++) { if (buffer[j] == 0) { buffer[j] = job; break; } } System.out.print("Buffer: "); for (int value : buffer) { System.out.print(value + " "); } System.out.println(); System.out.println("Producer will wait for " + i + " seconds"); try { Thread.sleep(i * 1000); } catch (InterruptedException e) { e.printStackTrace(); } flag[0] = false; } } } static class Consumer extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { flag[1] = true; turn = 0; while (flag[0] && turn == 0) ; System.out.println("Consumer is ready now."); // Critical Section: Remove from buffer int job = buffer[0]; buffer[0] = 0; System.out.println("Job " + job + " has been consumed"); System.out.print("Buffer: "); for (int value : buffer) { System.out.print(value + " "); } System.out.println(); System.out.println("Consumer will sleep for " + job + " seconds"); try { Thread.sleep(job * 1000); } catch (InterruptedException e) { e.printStackTrace(); } flag[1] = false; } } } public static void main(String[] args) { Producer producer = new Producer(); Consumer consumer = new Consumer(); producer.start(); consumer.start(); try { Thread.sleep(11000); // Program runs for 11 seconds } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("The clock ran out."); } } ``` Python3 ```import time import random import multiprocessing from multiprocessing import Process, Value, Array, Lock from queue import Full, Empty BSIZE = 8 PWT = 2 CWT = 10 RT = 10 def initializeBuffer(buf, size): for i in range(size): buf[i] = 0 def myrand(n): return random.randint(1, n) def producer(flag, turn, buf, state): index = 0 while state.value == 1: flag[1] = True print("Producer is ready now.\n") turn.value = 0 while flag[0] and turn.value == 0: pass # Critical Section Begin index = 0 while index < BSIZE: if buf[index] == 0: tempo = myrand(BSIZE * 3) print(f"Job {tempo} has been produced") buf[index] = tempo break index += 1 if index == BSIZE: print("Buffer is full, nothing can be produced!!!") print("Buffer: ", end="") for i in range(BSIZE): print(buf[i], end=" ") print("\n") # Critical Section End flag[1] = False if state.value == 0: break wait_time = myrand(PWT) print(f"Producer will wait for {wait_time} seconds\n") time.sleep(wait_time) def consumer(flag, turn, buf, state): index = 0 flag[0] = False while state.value == 1: flag[0] = True print("Consumer is ready now.\n") turn.value = 1 while flag[1] and turn.value == 1: pass # Critical Section Begin if buf[0] != 0: print(f"Job {buf[0]} has been consumed") buf[0] = 0 index = 1 while index < BSIZE: buf[index - 1] = buf[index] index += 1 buf[index - 1] = 0 else: print("Buffer is empty, nothing can be consumed!!!") print("Buffer: ", end="") for i in range(BSIZE): print(buf[i], end=" ") print("\n") # Critical Section End flag[0] = False if state.value == 0: break wait_time = myrand(CWT) print(f"Consumer will sleep for {wait_time} seconds\n") time.sleep(wait_time) if __name__ == "__main__": flag = Array('b', [False, False]) turn = Value('i', 1) buf = Array('i', range(BSIZE)) state = Value('i', 1) initializeBuffer(buf, BSIZE) t1 = time.time() producer_process = Process(target=producer, args=(flag, turn, buf, state)) consumer_process = Process(target=consumer, args=(flag, turn, buf, state)) producer_process.start() consumer_process.start() while True: t2 = time.time() if t2 - t1 > RT: state.value = 0 break producer_process.join() consumer_process.join() print("The clock ran out.") ``` C# ```using System; using System.Threading.Tasks; class Program { const int BSIZE = 8; const int PWT = 2; const int CWT = 10; const int RT = 10; static bool[] SHM1 = new bool[2]; static int[] SHM2 = new int[1]; static int[] SHM3 = new int[BSIZE]; static Random rand = new Random(); static void InitializeBuffer(int[] buf, int size) { Array.Fill(buf, 0); } static int MyRand(int n) => rand.Next(1, n + 1); static async Task Producer() { bool[] flag = SHM1; int[] turn = SHM2; int[] buf = SHM3; int index = 0; while (SHM2[0] == 1) { flag[1] = true; Console.WriteLine("Producer is ready now.\n"); turn[0] = 0; while (flag[0] && turn[0] == 0) ; // Critical Section Begin index = 0; while (index < BSIZE) { if (buf[index] == 0) { int tempo = MyRand(BSIZE * 3); Console.WriteLine(\$"Job {tempo} has been produced"); buf[index] = tempo; break; } index++; } if (index == BSIZE) Console.WriteLine("Buffer is full, nothing can be produced!!!\n"); Console.Write("Buffer: "); index = 0; while (index < BSIZE) Console.Write(\$"{buf[index++]} "); Console.WriteLine("\n"); // Critical Section End flag[1] = false; if (SHM2[0] == 0) break; int waitTime = MyRand(PWT); Console.WriteLine(\$"Producer will wait for {waitTime} seconds\n"); await Task.Delay(waitTime * 1000); } } static async Task Consumer() { bool[] flag = SHM1; int[] turn = SHM2; int[] buf = SHM3; int index = 0; flag[0] = false; while (SHM2[0] == 1) { flag[0] = true; Console.WriteLine("Consumer is ready now.\n"); turn[0] = 1; while (flag[1] && turn[0] == 1) ; // Critical Section Begin if (buf[0] != 0) { Console.WriteLine(\$"Job {buf[0]} has been consumed"); buf[0] = 0; index = 1; while (index < BSIZE) { buf[index - 1] = buf[index]; index++; } buf[index - 1] = 0; } else Console.WriteLine("Buffer is empty, nothing can be consumed!!!\n"); Console.Write("Buffer: "); index = 0; while (index < BSIZE) Console.Write(\$"{buf[index++]} "); Console.WriteLine("\n"); // Critical Section End flag[0] = false; if (SHM2[0] == 0) break; int waitTime = MyRand(CWT); Console.WriteLine(\$"Consumer will sleep for {waitTime} seconds\n"); await Task.Delay(waitTime * 1000); } } static async Task Main() { InitializeBuffer(SHM3, BSIZE); DateTime startTime = DateTime.Now; SHM2[0] = 1; // Initializing the state var producerTask = Producer(); var consumerTask = Consumer(); // Parent process will now wait for RT seconds before causing the child to terminate while ((DateTime.Now - startTime).TotalSeconds <= RT) ; SHM2[0] = 0; // Waiting for both tasks to finish await Task.WhenAll(producerTask, consumerTask); Console.WriteLine("The clock ran out.\n"); } } ``` JavaScript ```const { Worker } = require('worker_threads'); const BSIZE = 8; const PWT = 2; const CWT = 10; const RT = 10; // Function to initialize the buffer with zeros function initializeBuffer(buf, size) { for (let i = 0; i < size; i++) { buf[i] = 0; } } // Function to generate random number function myrand(n) { return Math.floor(Math.random() * n) + 1; } // Producer function async function producer(flag, turn, buf, state) { let index = 0; while (state === 1) { flag[1] = true; console.log("Producer is ready now.\n"); turn.value = 0; while (flag[0] && turn.value === 0) { // Wait until it's producer's turn } // Critical Section Begin index = 0; while (index < BSIZE) { if (buf[index] === 0) { const tempo = myrand(BSIZE * 3); console.log(`Job \${tempo} has been produced`); buf[index] = tempo; break; } index++; } if (index === BSIZE) { console.log("Buffer is full, nothing can be produced!!!"); } console.log("Buffer: " + buf.join(" ") + "\n"); // Critical Section End flag[1] = false; if (state === 0) { break; } const wait_time = myrand(PWT); console.log(`Producer will wait for \${wait_time} seconds\n`); await new Promise(resolve => setTimeout(resolve, wait_time * 1000)); } } // Consumer function async function consumer(flag, turn, buf, state) { let index = 0; flag[0] = false; while (state === 1) { flag[0] = true; console.log("Consumer is ready now.\n"); turn.value = 1; while (flag[1] && turn.value === 1) { // Wait until it's consumer's turn } // Critical Section Begin if (buf[0] !== 0) { console.log(`Job \${buf[0]} has been consumed`); buf[0] = 0; index = 1; while (index < BSIZE) { buf[index - 1] = buf[index]; index++; } buf[index - 1] = 0; } else { console.log("Buffer is empty, nothing can be consumed!!!"); } console.log("Buffer: " + buf.join(" ") + "\n"); // Critical Section End flag[0] = false; if (state === 0) { break; } const wait_time = myrand(CWT); console.log(`Consumer will sleep for \${wait_time} seconds\n`); await new Promise(resolve => setTimeout(resolve, wait_time * 1000)); } } // Main function function main() { const flag = [false, false]; const turn = { value: 1 }; const buf = Array.from({ length: BSIZE }, (_, i) => i); let state = 1; initializeBuffer(buf, BSIZE); const t1 = new Date().getTime() / 1000; const producer_worker = new Worker(producer, { workerData: [flag, turn, buf, state] }); const consumer_worker = new Worker(consumer, { workerData: [flag, turn, buf, state] }); producer_worker.on('error', (err) => console.error(err)); consumer_worker.on('error', (err) => console.error(err)); const t2 = new Date().getTime() / 1000; if (t2 - t1 > RT) { state = 0; } console.log("The clock ran out."); } // Run the main function main(); ```

Output:

`Producer is ready now.Job 9 has been producedBuffer: 9 0 0 0 0 0 0 0 Producer will wait for 1 secondsProducer is ready now.Job 8 has been producedBuffer: 9 8 0 0 0 0 0 0 Producer will wait for 2 secondsProducer is ready now.Job 13 has been producedBuffer: 9 8 13 0 0 0 0 0 Producer will wait for 1 secondsProducer is ready now.Job 23 has been producedBuffer: 9 8 13 23 0 0 0 0 Producer will wait for 1 secondsConsumer is ready now.Job 9 has been consumedBuffer: 8 13 23 0 0 0 0 0 Consumer will sleep for 9 secondsProducer is ready now.Job 15 has been producedBuffer: 8 13 23 15 0 0 0 0 Producer will wait for 1 secondsProducer is ready now.Job 13 has been producedBuffer: 8 13 23 15 13 0 0 0 Producer will wait for 1 secondsProducer is ready now.Job 11 has been producedBuffer: 8 13 23 15 13 11 0 0 Producer will wait for 1 secondsProducer is ready now.Job 22 has been producedBuffer: 8 13 23 15 13 11 22 0 Producer will wait for 2 secondsProducer is ready now.Job 23 has been producedBuffer: 8 13 23 15 13 11 22 23 Producer will wait for 1 secondsThe clock ran out.`
C++ ```//g++ -pthread /path/to/your/Solution.cpp -o your_program_name //In environments where threading is not supported by default, you need to explicitly link against the pthread library. #include <iostream> #include <vector> #include <chrono> #include <cstdlib> #include <ctime> #include <thread> const int BSIZE = 8; const int PWT = 1000; const int CWT = 4000; const int RT = 30000; bool shmid1 = false; int shmid2 = 0; std::vector<int> shmid3(BSIZE, 0); int shmid4 = 0; int state = 1; int myrand(int n) { return rand() % n + 1; } void producer() { while (state == 1) { shmid1 = true; std::cout << "Producer is ready now.\n"; std::this_thread::sleep_for(std::chrono::milliseconds(500)); shmid2 = 0; while (shmid1 && shmid2 == 0) {} // Critical Section Begin int index = 0; while (index < BSIZE) { if (shmid3[index] == 0) { const int tempo = myrand(BSIZE * 3); std::cout << "Job " << tempo << " has been produced\n"; shmid3[index] = tempo; break; } index++; } if (index == BSIZE) { std::cout << "Buffer is full, nothing can be produced!!!\n"; } std::cout << "Buffer: "; for (int val : shmid3) { std::cout << val << " "; } std::cout << "\n"; // Critical Section End shmid1 = false; if (state == 0) break; const int wait_time = myrand(PWT); std::cout << "Producer will wait for " << wait_time / 1000.0 << " seconds\n"; std::this_thread::sleep_for(std::chrono::milliseconds(wait_time)); } } void consumer() { shmid1 = false; std::this_thread::sleep_for(std::chrono::milliseconds(5000)); while (state == 1) { shmid1 = true; std::cout << "Consumer is ready now.\n"; std::this_thread::sleep_for(std::chrono::milliseconds(500)); shmid2 = 1; while (shmid1 && shmid2 == 1) {} // Critical Section Begin if (shmid3[0] != 0) { std::cout << "Job " << shmid3[0] << " has been consumed\n"; shmid3[0] = 0; int index = 1; while (index < BSIZE) { shmid3[index - 1] = shmid3[index]; index++; } shmid3[index - 1] = 0; } else { std::cout << "Buffer is empty, nothing can be consumed!!!\n"; } std::cout << "Buffer: "; for (int val : shmid3) { std::cout << val << " "; } std::cout << "\n"; // Critical Section End shmid1 = false; if (state == 0) break; const int wait_time = myrand(CWT); std::cout << "Consumer will sleep for " << wait_time / 1000.0 << " seconds\n"; std::this_thread::sleep_for(std::chrono::milliseconds(wait_time)); } } int main() { srand(time(nullptr)); // Start producer and consumer in separate threads (simulated) std::thread producer_thread(producer); std::thread consumer_thread(consumer); // Simulate program run for RT milliseconds for (int elapsed_time = 0; elapsed_time < RT; elapsed_time += 100) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } // Set state to 0 to stop producer and consumer state = 0; // Join threads producer_thread.join(); consumer_thread.join(); std::cout << "The clock ran out.\n"; return 0; } ``` Java ```import java.util.Random; public class ProducerConsumer { static final int BSIZE = 8; // Buffer size static final int PWT = 2; // Producer wait time limit static final int CWT = 10; // Consumer wait time limit static final int RT = 10; // Program run-time in seconds static volatile boolean state = true; static volatile boolean[] flag = new boolean[2]; static volatile int turn = 1; static volatile int[] buf = new int[BSIZE]; static int myrand(int n) { Random rand = new Random(); return rand.nextInt(n) + 1; } public static void main(String[] args) { Thread producer = new Thread(() -> { int index; while (state) { flag[1] = true; System.out.println("Producer is ready now.\n"); turn = 0; while (flag[0] && turn == 0) ; synchronized (buf) { index = 0; while (index < BSIZE) { if (buf[index] == 0) { int tempo = myrand(BSIZE * 3); System.out.println("Job " + tempo + " has been produced"); buf[index] = tempo; break; } index++; } if (index == BSIZE) System.out.println("Buffer is full, nothing can be produced!!!\n"); System.out.print("Buffer: "); for (int value : buf) { System.out.print(value + " "); } System.out.println("\n"); } flag[1] = false; if (!state) break; int wait_time = myrand(PWT); System.out.println("Producer will wait for " + wait_time + " seconds\n"); try { Thread.sleep(wait_time * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread consumer = new Thread(() -> { int index; flag[0] = false; try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } while (state) { flag[0] = true; System.out.println("Consumer is ready now.\n"); turn = 1; while (flag[1] && turn == 1) ; synchronized (buf) { if (buf[0] != 0) { System.out.println("Job " + buf[0] + " has been consumed"); buf[0] = 0; index = 1; while (index < BSIZE) { buf[index - 1] = buf[index]; index++; } buf[index - 1] = 0; } else System.out.println("Buffer is empty, nothing can be consumed!!!\n"); System.out.print("Buffer: "); for (int value : buf) { System.out.print(value + " "); } System.out.println("\n"); } flag[0] = false; if (!state) break; int wait_time = myrand(CWT); System.out.println("Consumer will sleep for " + wait_time + " seconds\n"); try { Thread.sleep(wait_time * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); producer.start(); consumer.start(); try { Thread.sleep(RT * 1000); } catch (InterruptedException e) { e.printStackTrace(); } state = false; try { producer.join(); consumer.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("The clock ran out.\n"); } } ``` Python3 ```import multiprocessing import random import time BSIZE = 8 # Buffer size PWT = 1 # Producer wait time limit CWT = 4 # Consumer wait time limit RT = 30 # Program run-time in seconds shmid1 = multiprocessing.Value('i', 0) shmid2 = multiprocessing.Value('i', 0) shmid3 = multiprocessing.Array('i', [0] * BSIZE) shmid4 = multiprocessing.Value('i', 0) state = multiprocessing.Value('i', 1) def myrand(n): return random.randint(1, n) def producer(): global state while state.value == 1: shmid1.value = True print("Producer is ready now.") time.sleep(0.5) # Simulate some processing time shmid2.value = 0 while shmid1.value == True and shmid2.value == 0: pass with shmid1.get_lock(), shmid3.get_lock(): # Critical Section Begin index = 0 while index < BSIZE: if shmid3[index] == 0: tempo = myrand(BSIZE * 3) print(f"Job {tempo} has been produced") shmid3[index] = tempo break index += 1 if index == BSIZE: print("Buffer is full, nothing can be produced!!!") print("Buffer:", ' '.join(map(str, shmid3))) # Critical Section End shmid1.value = False if state.value == 0: break wait_time = myrand(PWT) print(f"Producer will wait for {wait_time} seconds") time.sleep(wait_time) def consumer(): global state shmid1.value = False time.sleep(5) while state.value == 1: shmid1.value = True print("Consumer is ready now.") time.sleep(0.5) # Simulate some processing time shmid2.value = 1 while shmid1.value == True and shmid2.value == 1: pass with shmid1.get_lock(), shmid3.get_lock(): # Critical Section Begin if shmid3[0] != 0: print(f"Job {shmid3[0]} has been consumed") shmid3[0] = 0 index = 1 while index < BSIZE: shmid3[index - 1] = shmid3[index] index += 1 shmid3[index - 1] = 0 else: print("Buffer is empty, nothing can be consumed!!!") print("Buffer:", ' '.join(map(str, shmid3))) # Critical Section End shmid1.value = False if state.value == 0: break wait_time = myrand(CWT) print(f"Consumer will sleep for {wait_time} seconds") time.sleep(wait_time) if __name__ == "__main__": producer_process = multiprocessing.Process(target=producer) consumer_process = multiprocessing.Process(target=consumer) producer_process.start() consumer_process.start() time.sleep(RT) state.value = 0 producer_process.join() consumer_process.join() print("The clock ran out.") ``` C# ```using System; using System.Threading; using System.Collections.Generic; public class ProducerConsumer { static readonly int BSIZE = 8; // Buffer size static readonly int PWT = 2; // Producer wait time limit static readonly int CWT = 10; // Consumer wait time limit static readonly int RT = 10; // Program run-time in seconds static volatile bool state = true; static volatile bool[] flag = new bool[2]; static volatile int turn = 1; static volatile int[] buf = new int[BSIZE]; static Random rand = new Random(); static int MyRand(int n) { return rand.Next(1, n + 1); } static void Main(string[] args) { Thread producerThread = new Thread(() => { int index; while (state) { flag[1] = true; Console.WriteLine("Producer is ready now.\n"); turn = 0; while (flag[0] && turn == 0) ; lock (buf) { index = 0; while (index < BSIZE) { if (buf[index] == 0) { int tempo = MyRand(BSIZE * 3); Console.WriteLine(\$"Job {tempo} has been produced"); buf[index] = tempo; break; } index++; } if (index == BSIZE) Console.WriteLine("Buffer is full, nothing can be produced!!!\n"); Console.Write("Buffer: "); foreach (int value in buf) { Console.Write(\$"{value} "); } Console.WriteLine("\n"); } flag[1] = false; if (!state) break; int waitTime = MyRand(PWT); Console.WriteLine(\$"Producer will wait for {waitTime} seconds\n"); Thread.Sleep(waitTime * 1000); } }); Thread consumerThread = new Thread(() => { int index; flag[0] = false; Thread.Sleep(5000); while (state) { flag[0] = true; Console.WriteLine("Consumer is ready now.\n"); turn = 1; while (flag[1] && turn == 1) ; lock (buf) { if (buf[0] != 0) { Console.WriteLine(\$"Job {buf[0]} has been consumed"); buf[0] = 0; index = 1; while (index < BSIZE) { buf[index - 1] = buf[index]; index++; } buf[index - 1] = 0; } else Console.WriteLine("Buffer is empty, nothing can be consumed!!!\n"); Console.Write("Buffer: "); foreach (int value in buf) { Console.Write(\$"{value} "); } Console.WriteLine("\n"); } flag[0] = false; if (!state) break; int waitTime = MyRand(CWT); Console.WriteLine(\$"Consumer will sleep for {waitTime} seconds\n"); Thread.Sleep(waitTime * 1000); } }); producerThread.Start(); consumerThread.Start(); try { Thread.Sleep(RT * 1000); } catch (ThreadInterruptedException e) { Console.WriteLine(e.StackTrace); } state = false; try { producerThread.Join(); consumerThread.Join(); } catch (ThreadInterruptedException e) { Console.WriteLine(e.StackTrace); } Console.WriteLine("The clock ran out.\n"); } } ``` JavaScript ```const BSIZE = 8; // Buffer size const PWT = 1000; // Producer wait time limit in milliseconds const CWT = 4000; // Consumer wait time limit in milliseconds const RT = 30000; // Program run-time in milliseconds let shmid1 = false; let shmid2 = false; let shmid3 = new Array(BSIZE).fill(0); let shmid4 = 0; let state = 1; function myrand(n) { return Math.floor(Math.random() * n) + 1; } function producer() { while (state === 1) { shmid1 = true; console.log("Producer is ready now."); // Simulate some processing time awaitTimeout(500); shmid2 = 0; while (shmid1 && shmid2 === 0) {} // Critical Section Begin let index = 0; while (index < BSIZE) { if (shmid3[index] === 0) { const tempo = myrand(BSIZE * 3); console.log(`Job \${tempo} has been produced`); shmid3[index] = tempo; break; } index++; } if (index === BSIZE) { console.log("Buffer is full, nothing can be produced!!!"); } console.log("Buffer:", shmid3.join(" ")); // Critical Section End shmid1 = false; if (state === 0) break; const wait_time = myrand(PWT); console.log(`Producer will wait for \${wait_time / 1000} seconds`); awaitTimeout(wait_time); } } function consumer() { shmid1 = false; awaitTimeout(5000); while (state === 1) { shmid1 = true; console.log("Consumer is ready now."); // Simulate some processing time awaitTimeout(500); shmid2 = 1; while (shmid1 && shmid2 === 1) {} // Critical Section Begin if (shmid3[0] !== 0) { console.log(`Job \${shmid3[0]} has been consumed`); shmid3[0] = 0; let index = 1; while (index < BSIZE) { shmid3[index - 1] = shmid3[index]; index++; } shmid3[index - 1] = 0; } else { console.log("Buffer is empty, nothing can be consumed!!!"); } console.log("Buffer:", shmid3.join(" ")); // Critical Section End shmid1 = false; if (state === 0) break; const wait_time = myrand(CWT); console.log(`Consumer will sleep for \${wait_time / 1000} seconds`); awaitTimeout(wait_time); } } async function awaitTimeout(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } (async () => { producer(); consumer(); await awaitTimeout(RT); state = 0; console.log("The clock ran out."); })(); ```
`Producer is ready now.Job 13 has been producedBuffer: 13 0 0 0 0 0 0 0 Producer will wait for 1 secondsProducer is ready now.Job 19 has been producedBuffer: 13 19 0 0 0 0 0 0 Producer will wait for 1 secondsProducer is ready now.Job 24 has been producedBuffer: 13 19 24 0 0 0 0 0 Producer will wait for 1 secondsProducer is ready now.Job 14 has been producedBuffer: 13 19 24 14 0 0 0 0 Producer will wait for 1 secondsProducer is ready now.Job 22 has been producedBuffer: 13 19 24 14 22 0 0 0 Producer will wait for 2 secondsConsumer is ready now.Job 13 has been consumedBuffer: 19 24 14 22 0 0 0 0 Consumer will sleep for 4 secondsProducer is ready now.Job 21 has been producedBuffer: 19 24 14 22 21 0 0 0 Producer will wait for 2 secondsProducer is ready now.Job 24 has been producedBuffer: 19 24 14 22 21 24 0 0 Producer will wait for 2 secondsConsumer is ready now.Job 19 has been consumedBuffer: 24 14 22 21 24 0 0 0 Consumer will sleep for 7 secondsThe clock ran out.`

### Advantages of the Peterson Solution

1. With Peterson’s solution, multiple processes can access and share a resource without causing any resource conflicts.
2. Every process has a chance to be carried out.
3. It uses straightforward logic and is easy to put into practice.
4. Since it is entirely software dependent and operates in user mode, it can be used with any hardware.
eliminates the chance of a deadlock.

### Disadvantages of the Peterson’s Solution

1. Waiting for the other processes to exit the critical region may take a long time. We call it busy waiting.
2. On systems that have multiple CPUs, this algorithm might not function.
3. The Peterson solution can only run two processes concurrently.

Q1:What is synchronization in concurrent programming?Â

Synchronization refers to the coordination of multiple processes or threads to achieve a desired outcome. It involves using synchronization mechanisms like locks, semaphores, or mutexes to control access to shared resources and prevent race conditions or conflicts.

Q2:What are the common synchronization mechanisms used in concurrent programming?Â