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

在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 Orders

28                 //如果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 Fruit

17         {

18             Empty,

19             Apple,

20             Orange

21         };

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                 else

47                 {

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型信号量以避免死锁。

 

三、读者写者问题

 

一个文件,允许多个读者同时读取,只能允许一个写者同时写,写者写的时候不能读。试实现之。 

 

 1 using System;

 2 using System.Threading;

 3 

 4 namespace ReaderWriter

 5 {

 6     class ReaderWriter

 7     {

 8 

 9         //Warning : Some Error will occur if more than one Reader is newed

10         //Using Semaphore can solve this however here I take mutex as example to show the concept. 

11          static  int Readcount =0 ;

12          static  Mutex WMutex = new Mutex();

13          static Mutex RMutex = new Mutex();

14          static int buffer = 0;

15          static Random rand = new Random();

16 

17         static void Main(string[] args)

18         {

19             new Thread(new ThreadStart(Writer)).Start();

20             new Thread(new ThreadStart(Reader)).Start();

21             new Thread(new ThreadStart(Reader)).Start();

22 

23 

24             Console.Read();

25         }

26 

27         private static void Reader()

28         {

29             while (true)

30             {

31                 RMutex.WaitOne();

32                 if (Readcount == 0)

33                 {

34                     WMutex.WaitOne();

35                 }

36                 Readcount++;

37                 RMutex.ReleaseMutex();

38 

39                 Console.WriteLine("I have read this:{0}", buffer.ToString());

40 

41                 RMutex.WaitOne();

42                 Readcount--;

43                 if (Readcount == 0)

44                 {

45                     WMutex.ReleaseMutex();

46                 }

47                 RMutex.ReleaseMutex();

48                 Thread.Sleep(300);

49             }

50         }

51 

52         private static void Writer()

53         {

54             while (true)

55             {

56                 WMutex.WaitOne();

57                 buffer = rand.Next(1, 10);

58                 Console.WriteLine("Write {0}",buffer);

59                 WMutex.ReleaseMutex();

60                 Thread.Sleep(1000);

61             }

62         }

63     }

64 }

 

Rohan

2014-1-7

 

 

 

 

 

 

你可能感兴趣的:(操作系统)