zoukankan      html  css  js  c++  java
  • 操作系统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

     

     

     

     

  • 相关阅读:
    《Linux C一站式学习》第七章 结构体
    《Linux C一站式学习》第三章 简单的函数
    《Windows程序设计》第一章 起步
    CSS在线课程学习笔记
    《Windows程序设计》第三章 窗口和消息
    window.open与window.showModalDialog中主页面与从页面间的通信(原创) 中庸
    php文件实现将大文件导入到mysql数据库中
    我为何爱读代码?你为何也应当爱?
    解决phpMyAdmin导入mysql数据库超过2M的问题
    对linux交换分区swap的一些认识总结
  • 原文地址:https://www.cnblogs.com/RohanVon/p/3507826.html
Copyright © 2011-2022 走看看