同步与互斥中的购票和退票问题的PV操作与实现
进程互斥
进程互斥是进程之间的间接制约关系。当一个进程进入临界区使用临界资源时,另一个进程必须等待。只有当使用临界资源的进程退出临界区后,这个进程才会解除阻塞状态。
比如进程B需要访问打印机,但此时进程A占有了打印机,进程B会被阻塞,直到进程A释放了打印机资源,进程B才可以继续执行。
C#模拟火车站买票的PV问题实例代码如下
class Program
{
//关于火车站买票的PV问题实例
static Mutex mut = new Mutex();
static void Main(string[] args)
{
for (int i = 1; i <= 10; i++)
{
Thread thread1 = new Thread(new ThreadStart(Sell));
Thread thread2 = new Thread(new ThreadStart(Return));
thread1.Name = string.Format("{0}号售票窗口", i);
thread2.Name = string.Format("{0}号退票窗口", i);
thread1.Start();
thread2.Start();
}
}
static int Count=100; //记录剩余火车票数目(共享资源)
static void Sell() //售票窗口模拟
{
mut.WaitOne(); //P操作
Console.WriteLine("{0}开始售票", Thread.CurrentThread.Name);
int temp = Count;
if(temp==0)
{
Console.WriteLine("车票已售完");
}
else
{
Console.WriteLine("余票{0}张",temp);
Console.WriteLine("请选择购买车票数");
int num = int.Parse(Console.ReadLine());
if (temp < num)
{
Console.WriteLine("购票失败,剩余票数{0}张",Count);
Console.WriteLine("***********************************");
Console.WriteLine();
}
else
{
temp = temp - num;
Count = temp;
Console.WriteLine("购票成功,购票{0}张,剩余票数{1}张",num , Count);
Console.WriteLine("***********************************");
Console.WriteLine();
}
}
mut.ReleaseMutex(); // V操作
}
static void Return() //退票窗口模拟
{
mut.WaitOne(); //P操作
Console.WriteLine("{0}开始退票", Thread.CurrentThread.Name);
int temp = Count;
Console.WriteLine("请选择退票数目");
int num = int.Parse(Console.ReadLine());
temp = temp + num;
Count = temp;
Console.WriteLine("退票成功,退票{0}张,余票{1}张", num, Count);
Console.WriteLine("***********************************");
Console.WriteLine();
mut.ReleaseMutex(); //V操作
}
运行结果如下图:
进程同步
进程同步也是进程之间直接的制约关系,是为完成某种任务而建立的两个或多个线程,这个线程需要在某些位置上协调他们的工作次序而等待、传递信息所产生的制约关系。进程间的直接制约关系来源于他们之间的合作。
比如说进程A需要从缓冲区读取进程B产生的信息,当缓冲区为空时,进程B因为读取不到信息而被阻塞。而当进程A产生信息放入缓冲区时,进程B才会被唤醒。
C# 模拟消费者与生产者实例如下:
class Program
{
private static Mutex mut = new Mutex();
private static Semaphore empty = new Semaphore(5, 10);//缓存区空闲,每次允许5个线程往缓冲区存数据
private static Semaphore full = new Semaphore(0, 10);//缓冲区满
static void Main(string[] args)
{
for (int i = 1; i < 10; i++)
{
Thread producer = new Thread(new ThreadStart(Producer));
Thread customer = new Thread(new ThreadStart(Customer));
producer.Name = string.Format("生产者{0}", i);
customer.Name = string.Format("消费者{0}", i);
producer.Start();
customer.Start();
}
}
private static void Producer()
{
Console.WriteLine("{0}准备就绪", Thread.CurrentThread.Name);
empty.WaitOne();
mut.WaitOne();
Console.WriteLine("{0}生产完成,产品放入仓库", Thread.CurrentThread.Name);
Thread.Sleep(3000);
mut.ReleaseMutex();
full.Release();
}
private static void Customer()
{
Console.WriteLine("{0}准备就绪", Thread.CurrentThread.Name);
Thread.Sleep(3000);
full.WaitOne();
mut.WaitOne();
Console.WriteLine("{0}消费完成,产品取出仓库", Thread.CurrentThread.Name);
mut.ReleaseMutex();
empty.Release();
}
}
运行结果如下图: