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

来源:互联网 时间:1970-01-01

在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

 

 

 

 

 

 


相关阅读:
Top