Operating Systems

advertisement
Synchronization
Producer/Consumer Problem
Abstract
The producer/consumer problem is a classical synchronization
exercise. The problem defines an arbitrary number of so-called
producers which create goods and consumers which consume
these goods. A bounded buffer of size n mediates among
producers and consumers and adapts to the different execution
speeds of all the involved processes resp. threads. Besides
mutual exclusion issues, semaphores are required to block
consumers until consumable goods are inside the buffer and to
block producers until there is free space available inside the
buffer to deposit additional goods. It is noteworthy that for
these additional semaphores, the semaphore functions are
called by opposite processes or threads (asymmetrical
solution).
Synchronization - PC with Semaphores
2
Producers
Motivation
Buffer
• n threads produce some good
Consumers
• m threads consume some good
• Bounded buffer between producers and consumers
– adapt to varying execution speeds
– minimize waiting time
• How to synchronize the n+m threads?
Synchronization - PC with Semaphores
3
Example
Buffer with
1 slot
Consumer
Producer
Synchronization - PC with Semaphores
4
Outline of Buffer
public class Buffer
{
public Buffer ( int n )
{
}
/// Inserts another good into the buffer.
/// May block until free space is available.
public void Produce ( int good )
{
}
/// Consumes a good stored inside the buffer.
/// May signal blocked producer threads.
public int Consume ()
{
return 42;
}
}
Synchronization - PC with Semaphores
5
Producer (C#)
public class Producer
{
public Producer ( Buffer b )
{
buffer = b;
my_id = this.GetHashCode();
ThreadStart ts = new ThreadStart(Run);
my_thread = new Thread(ts);
my_thread.Start();
}
private void Run ()
{
Console.WriteLine("Producer {0}: started ...",my_id);
int good = this.GetHashCode() * 1000000;
while (true)
{
buffer.Produce(good);
Console.WriteLine("Producer {0}: good {1} stored",my_id,good);
good++;
}
}
private Buffer buffer;
private Thread my_thread;
private int my_id;
}
Synchronization - PC with Semaphores
6
Consumer (C#)
public class Consumer
{
public Consumer ( Buffer b )
{
buffer = b;
my_id = this.GetHashCode();
ThreadStart ts = new ThreadStart(Run);
my_thread = new Thread(ts);
my_thread.Start();
}
private void Run ()
{
Console.WriteLine("Consumer {0}: started ...",my_id);
while (true)
{
int good = buffer.Consume();
Console.WriteLine("Consumer {0}: good {1} retrieved",my_id,good);
}
}
private Buffer buffer;
private Thread my_thread;
private int my_id;
}
Synchronization - PC with Semaphores
7
Exercise
• Implement the buffer
– Producers must block if buffer is full
– Consumers must block if buffer is empty
– Access to shared data structures should be
mutally exclusive
• Examine the running solution
Synchronization - PC with Semaphores
8
The Buffer (C#)
public class Buffer
{
public Buffer ( int n )
{
this.n = n;
slots = new int[n];
mutex = new Semaphore(1);
slots_available = new Semaphore(n);
goods_available = new Semaphore(0);
}
…
private
private
private
private
private
private
private
int n;
int [] slots;
int free = 0;
int used = 0;
Semaphore mutex;
Semaphore slots_available;
Semaphore goods_available;
public void Produce ( int good )
{
slots_available.P();
mutex.P();
slots[free] = good;
free = (free+1) % n;
mutex.V();
goods_available.V();
}
public int Consume ()
{
goods_available.P();
mutex.P();
int good = slots[used];
used = (used+1) % n;
mutex.V();
slots_available.V();
return good;
}
}
Synchronization - PC with Semaphores
9
Program Behavior
Program Visualization
Consumer
Producers
Program State
Synchronization - PC with Semaphores
10
Resources
• Every textbook on operating systems has a section on
solving the producer/consumer problem with
semaphores
• The "Little Book on Semaphores" by Allen B. Downey
Synchronization - PC with Semaphores
11
Download