Producer-Consumer Problem
A producer process and a consumer process communicate via a buffer.
- Producer Cycle:
    - Produce item.
- Deposit in buffer.
 
- Consumer Cycle:
    - Extract item from buffer.
- Process the item.
 
There can be many producers and consumers, sometimes in a chain.
Issues
We have to ensure that:
- Producer cannot put items in a full buffer.
- Consumer cannot extract items from buffer if it is empty.
- Buffer is not accessed by two thread simultaneously.
Implementation
Main Thread
public class Prodcon
{
	public static void main (String args[])
	{ // Create buffer, producer & consumer
		Buffer b = new Buffer();
		Producer p = new Producer(b);
		Consumer c = new Consumer(b);
		p.start(); c.start();
		...
	}
}
Producer and Consumer Classes
class Producer extends Thread {
private Buffer b;
	public Producer (Buffer buf) {
		b = buf;
	}
	public void run() {
		int m;
		...
		b.insert(m);
		...
	}
}
Consumer is similar, but calls n = b.remove()
Buffer Class With Semaphore
class Buffer {
	private int v;
	private volatile boolean empty=true;
	
	public void insert (int x) {
		while (!empty)
			; // null loop
		empty = false;
		v = x;
	}
	public int remove() {
	while (empty)
		; // null loop
	empty = true;
	return (v);
	}
}
- The emptyboolean tells us if the buffer is empty or not.- 
        volatileensures the computer will re-load the variable each time it is tested, rather than transferring it to a register.This says that the value could change without the compiler being aware. 
 
- 
        
- A producer will wait while the buffer is full. A consumer will wait while it is empty.
    - Busy waiting (spinlock)
- This simulates the waitoperation.
 
- Busy waiting is inefficient
    - A thread or process does nothing useful while it has the CPU.
- Spinlocks are useful only in a multiprocessor situation when expected wait time is very short.
 
Yielding
It may be more efficient for a waiting thread or process to relinquish control of the CPU:
public void insert (int x) {
	while(!empty)
		Thread.yield();
	empty = false;
	v = x;
}
The yield() call tells the JVM that the thread is willing to give up the CPU.
- The JVM might ignore it depending on the implementation.
    - This is why it is in a whileloop so that!emptyis tested many times.
 
- This is why it is in a 
- It is non-deterministic and platform dependant.