I am studying mutual exclusion in college, and decided to write a few producer/consumer programs. I wrote a busy waiting program, a monitor program, a semaphore program, and a mutex program. They all appear to work correctly; however, the first three programs generally run until the buffer is full/empty, then switch threads and continue the process. The mutex solution as a general rule switches threads every time a value is produced/consumed, although I have tested it and this is not required - each thread can run independently. Also, it will occasionally crash, but then if I run it again, it will be fine. Does anyone know why this runs this way? Am I doing something wrong here? This is my code:
class Program
{
const int BuffSize = 10;
char[] Buffer = new char[BuffSize];
volatile int Avail = 0;
int ValuesToProduce = 95;
Mutex _Buffer = new Mutex(false);
Mutex IsFull = new Mutex(true);
Mutex IsEmpty = new Mutex(true);
public void Produce()
{
for (int i = 0; i < ValuesToProduce; i++)
{
while (Avail == BuffSize)
{
Console.WriteLine("Wait Producer:");
IsFull.WaitOne(1000);
}
_Buffer.WaitOne();
Buffer[i % BuffSize] = (char)(32 + i % 95);
Avail++;
Console.WriteLine("Produced: {0}", Buffer[i % BuffSize]);
_Buffer.ReleaseMutex();
try
{
IsEmpty.ReleaseMutex();
}
catch
{
}
}
}
public void Consume()
{
for (int i = 0; i < ValuesToProduce; i++)
{
while (Avail < 1)
{
Console.WriteLine("Wait Consumer:");
IsEmpty.WaitOne(1000);
}
_Buffer.WaitOne();
char c = Buffer[i % BuffSize];
Avail--;
Console.WriteLine("Consumed: {0}", Buffer[i % BuffSize]);
_Buffer.ReleaseMutex();
try
{
IsFull.ReleaseMutex();
}
catch
{
}
}
}
}
class Test
{
static void Main(string[] args)
{
Program program = new Program();
Thread p = new Thread(new ThreadStart(program.Produce));
Thread c = new Thread(new ThreadStart(program.Consume));
p.Start();
c.Start();
}
}
Edit:
As proof that it is running through completion, here is a screenshot of the output: