操作系统PV操作——进程同步问题(C#实现)

8/3/2015来源:C#应用人气:2459

操作系统PV操作——进程同步问题(C#实现)

Posted on 2014-01-06 20:15 Rohan 阅读(...) 评论(...) 编辑 收藏

在C#中,用于同步的主要是Mutex类与Semaphore类。位于System.Threading命名空间中。

在这两个种对象的方法中,P操作对应的是WaitOne()方法,V操作对应的是ReleaseMutex()与Release()方法。

下面是用C#解决几大PV操作经典问题及其变形的代码。

一、生产者消费者问题

1.最简单的情况:一个生产者,一个消费者,共用一个缓冲区进行生产消费。

 1 using System; 2 using System.Threading; 3  4 namespace PRoducerCustomer1_SingleBuffer 5 { 6     class ProducerCustomer1_SingleBuffer 7     { 8         static Mutex mutex = new Mutex(); 9         static void Main(string[] args)10         {11             new Thread(new ThreadStart(Producer)).Start();12             new Thread(new ThreadStart(Customer)).Start();    13             Console.Read();14         }15 16         private static void Producer()17         {18             while (true)19             {20                 mutex.WaitOne();21                 Console.WriteLine("Producer is working!");22                 mutex.ReleaseMutex();23                 Thread.Sleep(400);24             }25         }26 27         private static void Customer()28         {29             while (true)30             {31                 mutex.WaitOne();32                 Console.WriteLine("customer is working");33                 mutex.ReleaseMutex();34                 Thread.Sleep(400);35             }36         }37     }38 }

2.现在稍微复杂一些,生产者与消费者共用一个大小为n的环形缓冲区。本例中n取10.

 1 using System; 2 using System.Threading; 3  4 namespace ProducerCustomer2_MultiBuffer 5 { 6     class ProducerCustomer2_MultiBuffer 7     { 8         static Mutex mutex = new Mutex(); 9         static Semaphore empty = new Semaphore(10,10);10         static Semaphore full = new Semaphore(0,10);11         static int[] buffer = new int[10];12         static Random rand = new Random();13 14         static void Main(string[] args)15         {16             new Thread(new ThreadStart(Producer)).Start();17             new Thread(new ThreadStart(Customer)).Start();18             Console.Read();19         }20 21         private static void Producer()22         {23             uint ppointer=0;24             int temp;25             while (true)26             {      27                 //!!!!Attention!!!!!NEVER MIX Orders28                 //如果empty与mutex的顺序反了,就会发生死锁!29                 empty.WaitOne();30                 mutex.WaitOne();31                 temp = rand.Next(1, 100);32                 buffer[ppointer] = temp;33                 Console.WriteLine("Producer works at {0} with {1}",ppointer,temp);34                 ppointer = (ppointer + 1)%10;35                 mutex.ReleaseMutex();36                 full.Release();37                 Thread.Sleep(400);38             }39         }40 41         private static void Customer()42         {43             uint cpointer=0;44             int temp;45             while (true)46             {47                 full.WaitOne();48                 mutex.WaitOne();49                 temp = rand.Next(1, 100);50                  temp = buffer[cpointer];51                 Console.WriteLine("Customer gains at {0} with {1}", cpointer, temp);52                 cpointer = (cpointer + 1) % 10;53                 mutex.ReleaseMutex();54                 empty.Release();55                 Thread.Sleep(400);56             }57         }58     }59 }

3.问题再升级:

桌上有一个空盘子,只允许放一个水果。爸爸可以放苹果。也可以放橘子。儿子要吃苹果,女儿要吃橘子。试实现之。

 1 using System; 2 using System.Threading; 3  4 namespace ProducerCustomer3_Fruit 5 { 6     internal class ProducerCustomer3_Fruit 7     { 8         private static Mutex mutex = new Mutex(); 9         private static Semaphore Sempty = new Semaphore(1, 1);10         private static Semaphore Sorange = new Semaphore(0, 1);11         private static Semaphore Sapple = new Semaphore(0, 1);12 13         private static Fruit buffer = 0;14         private static Random rand = new Random();15 16         public enum Fruit17         {18             Empty,19             Apple,20             Orange21         };22 23         private static void Main(string[] args)24         {25             new Thread(new ThreadStart(Papa)).Start();26             new Thread(new ThreadStart(Son)).Start();27             new Thread(new ThreadStart(Daughter)).Start();28             Console.Read();29         }30 31         private static void Papa()32         {33             while (true)34             {35                 int temp = 0;36                 Sempty.WaitOne();37                 mutex.WaitOne();38                 temp = rand.Next(1,3);39                 if (temp == 1)40                 {41                     Console.WriteLine("Papa put an apple");42                     buffer = Fruit.Apple;43                     mutex.ReleaseMutex();44                     Sapple.Release();45                 }46                 else47                 {48                     Console.WriteLine("Papa put an Orange");49                     buffer = Fruit.Orange;50                     mutex.ReleaseMutex();51                     Sorange.Release();52                 }53                 Thread.Sleep(400);54             }55         }56 57         private static void Son()58         {59             while (true)60             {61                 Sapple.WaitOne();62                 mutex.WaitOne();63                 Console.WriteLine("Son  eat an {0}", buffer);64                 mutex.ReleaseMutex();65                 Sempty.Release();66                 Thread.Sleep(400);67             }68         }69 70         private static void Daughter()71         {72             while (true)73             {74                 Sorange.WaitOne();75                 mutex.WaitOne();76                 Console.WriteLine("Daughter  eat an {0}", buffer);77                 mutex.ReleaseMutex();78                 Sempty.Release();79                 Thread.Sleep(400);80             }81         }82     }83 }

二、哲学家进餐问题

五个哲学家围着桌子共同进餐,每个哲学家两侧各有一支筷子。试设计同步算法,使哲学家都能吃上饭。

 1 using System; 2 using System.Threading; 3  4 namespace PhilosophersProblem 5 { 6     class PhilosophersProblem 7     { 8         static Semaphore[] chopsticks = { new Semaphore(1, 1) 9                                             , new Semaphore(1, 1)10                                             , new Semaphore(1, 1)11                                             , new Semaphore(1, 1),12                                             new Semaphore(1, 1), };13        14         static void Main(string[] args)15         {16             for (int i = 0; i < 5; i++)17             {18                 new Thread(new ParameterizedThreadStart(philosopher)).Start(i);19             }20             Console.Read();21         }22 23         private static void philosopher(object input)24         {25             int i = (int)input;26             chopsticks[i].WaitOne();27             chopsticks[(i + 1)%5].WaitOne();28 29             Console.WriteLine("Philosopher{0}: I am eating",i);30             Thread.Sleep(1000);31 32             chopsticks[i].Release();33             chopsticks[(i + 1)%5].Release();34         }35     }36 }

对于此类问题,应尽量使用信号量集或者and型信号量以避免死锁。

三、读者写者问题