I am not new to C# but I am new to the Thread and Monitor classes. I'm trying to implement a "simple" reader/writer program using "Airline Reservation" as a base. This is a "homework question" taken from the book C# How to Program (Introducing .NET and Web Services) by Deitel.
Here is what I have so far:
This is the class that the Readers and Writers access synchronously. In the interests of brevity and space, I have removed most comments from these classes.
namespace Airline_Reservation
{
// Represents a single airline reservation
class Flight
{
private string reservation;
public Flight()
{
reservation = "Airline: Unknown\nDate: Unknown\nDeparting Gate: Unknown\n";
}
public string Reservation
{
get { return reservation; }
set { reservation = value; }
}
public override string ToString() { return Reservation; }
// This is a required method
public void StartReading() { Monitor.Enter(this); }
// This is a required method
public void StopReading()
{
Monitor.Pulse(this);
Monitor.Exit(this);
}
// This is a required method
public void StartWriting() { Monitor.Enter(this); }
// This is a required method
public void StopWriting()
{
Monitor.Pulse(this);
Monitor.Exit(this);
}
}
}
Here is the reader:
namespace Airline_Reservation
{
class Reader
{
private string name;
private static int counter = 0;
private readonly Flight flightInfo;
public Reader(Flight info)
{
counter += 1;
name = "Reader " + counter;
this.flightInfo = info;
}
public Reader(Flight info, string name)
{
Name = name;
this.flightInfo = info;
}
public string Name
{
get { return name; }
set { name = value; }
}
// This is a required method
public void QueryReservation()
{
flightInfo.StartReading();
Console.WriteLine(Name + " reading flight reservation:\n" + flightInfo.ToString());
flightInfo.StartReading();
}
}
}
And here is the writer:
namespace Airline_Reservation
{
class Writer
{
private string name;
private static int counter = 0;
private Flight flightInfo;
private string airlineName;
private string date;
private string gate;
public Writer(Flight flight)
{
counter += 1;
name = "Writer " + counter;
flightInfo = flight;
}
public Writer(Flight flight, string name)
{
Name = name;
flightInfo = flight;
}
public string Name
{
get { return name; }
set { name = value; }
}
public string Airline
{
get { return airlineName; }
set { airlineName = value; }
}
public string Date
{
get { return date; }
set { date = value; }
}
public string Gate
{
get { return gate; }
set { gate = value; }
}
// This is a required method
public void MakeReservation()
{
Console.WriteLine(Name + " Making reservation . . .");
string flightDetails = "Airline: " + Airline + "\nDate: " + Date + "\nGate: " + Gate + "\n";
flightInfo.StartWriting();
flightInfo.Reservation = flightDetails;
flightInfo.StopWriting();
Console.WriteLine(Name + " Completed reservation.");
Console.WriteLine(flightDetails);
}
// This is a required method
public void CancelReservation()
{
Console.WriteLine(Name + " Cancelling reservation . . .");
string flightDetails = "Airline: Unknown\nDate: Unknown\nGate:Unknown\n";
flightInfo.StartWriting();
flightInfo.Reservation = flightDetails;
flightInfo.StopWriting();
Console.WriteLine(Name + " Completed cancellation . . .");
}
}
}
I needed a place for the Writer to write into the Flight object so I added three private members to the Writer, adding the values from the main program class.
Here is my main program
namespace Airline_Reservation
{
class Program
{
static void Main(string[] args)
{
Flight info = new Flight();
Reader rdr1 = new Reader(info);
Reader rdr2 = new Reader(info);
Reader rdr3 = new Reader(info);
Reader rdr4 = new Reader(info);
Reader rdr5 = new Reader(info);
Writer wtr1 = new Writer(info);
wtr1.Airline = "Air Canada";
wtr1.Date = "03/1/2020";
wtr1.Gate = "J6";
Thread rdrThread1 = new Thread(new ThreadStart(rdr1.QueryReservation));
Thread rdrThread2 = new Thread(new ThreadStart(rdr2.QueryReservation));
Thread wtrThread1 = new Thread(new ThreadStart(wtr1.MakeReservation));
Thread rdrThread3 = new Thread(new ThreadStart(rdr3.QueryReservation));
Thread rdrThread4 = new Thread(new ThreadStart(rdr4.QueryReservation));
Thread wtrThread2 = new Thread(new ThreadStart(wtr1.CancelReservation));
Thread rdrThread5 = new Thread(new ThreadStart(rdr4.QueryReservation));
rdrThread1.Priority = ThreadPriority.BelowNormal;
rdrThread2.Priority = ThreadPriority.Lowest;
rdrThread3.Priority = ThreadPriority.Normal;
rdrThread4.Priority = ThreadPriority.BelowNormal;
rdrThread5.Priority = ThreadPriority.Normal;
wtrThread1.Priority = ThreadPriority.AboveNormal;
wtrThread2.Priority = ThreadPriority.AboveNormal;
rdrThread1.Start();
rdrThread2.Start();
rdrThread3.Start();
rdrThread4.Start();
rdrThread5.Start();
wtrThread1.Start();
wtrThread2.Start();
}
}
}
When I run this, I get the following, every time:
Reader 1 reading flight reservation:
Airline: Unknown
Date: Unknown
Departing Gate: Unknown
Writer 1 Cancelling reservation . . .
Writer 1 Making reservation . . .
... and then the program freezes and doesn't proceed. I suspect a deadlock somewhere but since this is my first program explicitly using threads, I don't know where to start.
Any advice or comments?