Producer Consumer Problem

There are two processes in the consumer problem. One is the PRODUCER, and the other is the CONSUMER process. The PRODUCER produces the items, and the CONSUMER consumes them.

Both processes are running parallel and share some resources like main memory. That’s why these are also known as cooperative processes.  However the problem is that these processes are not synchronized.

Producer Consumer Problem With Example:

In the producer section, the producer produces an item and puts it into a buffer, which is a memory, and the consumer takes out the item from the buffer. In this way, buffer memory is used as shared memory in these two processes.

 The explanation of the Producer-Consumer Problem program in C language is.

Int COUNT = 0; // Shared variable tells how many items are there in the memory
Int N=10 // Shared variable where N (0-9) is the size of buffer.

Void Producer (void) {
Int IN =0 // local Variable that works as pointer
Int itemP // Create an local integer Variable ItemP
While(true) //condition always true
{Produce_item(itemP); // function for which item to produce i.e. pass X1 value in function to produce item X1. While(COUNT ==N);
// Buffer is full ( process go to infinite loop, if condition is false then program next execute)
Buffer[IN] = itemP; // place item in buffer location 0
IN = (IN+1) MOD  N; // IN Moves to Next empty slot in buffer. Count = Count +1; // count value incremented by 1 (because one item is produced in buffer) } }

Void Consumer(void) {
Int OUT =0 // local Variable that works as pointer
Int itemC // Create an local integer Variable ItemC 
While(true) //condition always true {While(COUNT ==0);  ( process go to infinite loop, if condition is false then program next execute) Item C = Buffer(OUT); // Buffer location value stored in itemC
OUT= (OUT+1) MOD N; // OUT Moves to Next filled slot in buffer Count = Count -1; // count value decremented by 1 (because one item is consumed in buffer)
Execute_item(itemC); // further processing on consumed item } }

Buffer (Memory)

Where 0 to 6 are different locations of memory. X1 and X2 are items produced by producer Code. Here, we test the producer-consumer problem through different cases.

CASE 01:

When a producer produces an item by executing producer code, the consumer consumes that item by executing consumer code. Make sure there is no interruption during execution.  Then there will be no problem with that code. Producer-consumer code works perfectly.

CASE 02:

Let us execute the producer code. buffer already contains 5 items. So, COUNT = 5. Now CPU wants to execute the following instruction to produce the 6th item in the producer code.

COUNT =COUNT +1

To execute the above instruction, the CPU has to execute three micro-instructions given below,

LOAD R1, M[COUNT] // Load the value of COUNT in Register( R1) from COUNT, So R1=5
INCR[R1] // increment the Register ( R1) value by 1 So, R1=6
STORE M[COUNT], R1 // Save the R1 value in Memory

Suppose an interrupt is occurring just after the execution of the second micro-instruction in the Producer section as

LOAD R1, M[COUNT]
INCR[R1]
Any Interrupt occur
STORE M[COUNT], R1

       Till here, the value of R1 is incremented to 6 because (COUNT =5). But it is still not loaded in the main memory. Still, COUNT= 5 in main memory.  Execution-record of this process is saved in its PCB by OS. And CPU control preempts Consumer code.

Now, when the CPU is executing the following instruction in the consumer section, then,

COUNT = COUNT -1

To execute the above instruction, the CPU has to execute again three micro-instructions.

LOAD R2, M[COUNT] // Load the value of COUNT in Register( R2) from COUNT , So R1=5
DECR [R1] // R1 decremented by 1, So R1=4
STORE M[COUNT], R2 // Save the R2 value in COUNT  Memory

And let’s suppose again an interrupt occurs just after the second micro-instruction in the consumer section

LOAD R2, M[Count]
DECR [R2]
Any interrupt occur
STORE M[Count], R2

In this way, the value of R2 becomes 4. It is because of minus 1 in R2. But R2 is still not saved in the main memory. Still, COUNT= 5 in main memory. Then, the CPU again preempted the producer code. Then, the OS stores the record of this process in its PCB, and the CPU shifts to the Producer section to execute the remaining code. Now it starts from the third micro-instruction for execution.

As the CPU Executes the third instruction of consumer code, the value of the COUNT variable becomes 6, and it is stored in the main memory because the OS resumes the process instead of restarting.

After executing the producer section, the CPU pre-empts back to the consumer section to execute the remaining code starting from the third micro-instruction. Now, the COUNT variable value becomes 4 and is stored in the main memory.

Instruction execution Series: Producer Instruction1, instruction2 Consumer Instruction1, instruction2 Producer instruction3 Consumer Instruction3.

Conclusion:

As the CPU executes both processes parallel. As in the above example, process P1 is incremented by 1, and the COUNT variable becomes +1. P2 is decremented, and the 1 COUNT variable becomes -1. So, The Result should be 5 (5+1-1=5) but the value of COUNT in main memory is 4, which is incorrect.

The producer consumer problem can be overcome by semaphore, monitoring Paterson Solution, etc.

Note: Reason of CPU preempt are