C#多线程——多线程访问共同的代码或者对象

来源:互联网 发布:c 开发 gprs源码 编辑:程序博客网 时间:2024/05/17 22:21

多线程对共同资源的访问,往往会造成数据的混乱和不可预料的结果,因此一般需要加锁访问进行互斥访问。

所谓“互斥访问”是指,一段代码或者公共变量,在一个时刻只允许一个线程去访问,其他的线程需要等待,直到改线程处理完毕并通知下一个等待的线程去处理。

1、可以用“Lock”来提供代码的互斥访问:

[csharp] view plain copy
  1. lock (一个类的示例、静态变量的类名)  
  2. {  
  3.         // 代码  
  4. }  

2、可以用“Monitor”来提供变量的互斥访问:

[csharp] view plain copy
  1. int money;  
  2. Monitor.Enter(money);  
  3. // money++或者money--;  
  4. Monitor.Exit(money);  

Monitor的工作原理是:Monitor维护了两个队列,一个是预备队列,其中保存准备获取锁的线程;另一个是等待队列,保存正在等待这个对象状态改变的线程。当锁被一个线程释放时,调用Monitor.Pulse()方法,将等待队列中的第一个线程放到预备队列中。

 

下面是一个使用Lock和Monitor的例子:

[csharp] view plain copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using System.Threading;  
  5.   
  6. namespace Demo  
  7. {  
  8.     public class ProductClass  
  9.     {  
  10.         int products;  
  11.         bool enableGet = false;   // If ture, consumer can get product, otherwise producer is producing.  
  12.   
  13.         public int GetProducts()  
  14.         {  
  15.             lock (this)  
  16.             {  
  17.                 if (!enableGet)  
  18.                 {  
  19.                     try  
  20.                     {  
  21.                         Monitor.Wait(this);  
  22.                     }  
  23.                     catch (SynchronizationLockException ex)  
  24.                     {  
  25.                         Console.WriteLine("[SynchronizationLockException Error]: " + ex.ToString());  
  26.                     }  
  27.                     catch (ThreadInterruptedException ex)  
  28.                     {  
  29.                         Console.WriteLine("[ThreadInterruptedException Error]: " + ex.ToString());  
  30.                     }  
  31.                 }  
  32.                 Console.WriteLine("Consume: {0}", products);  
  33.   
  34.                 // Reset to be false after getting products.  
  35.                 enableGet = false;  
  36.   
  37.                 // Notify producing thread to produce products  
  38.                 Monitor.Pulse(this);  
  39.             }  
  40.             return products;  
  41.         }  
  42.   
  43.         public void ProduceProducts(int products)  
  44.         {  
  45.             lock (this)  
  46.             {  
  47.                 if (enableGet)  
  48.                 {  
  49.                     try  
  50.                     {  
  51.                         Monitor.Wait(this);  
  52.                     }  
  53.                     catch (SynchronizationLockException ex)  
  54.                     {  
  55.                         Console.WriteLine("[SynchronizationLockException Error]: " + ex.ToString());  
  56.                     }  
  57.                     catch (ThreadInterruptedException ex)  
  58.                     {  
  59.                         Console.WriteLine("[ThreadInterruptedException Error]: " + ex.ToString());  
  60.                     }  
  61.                 }  
  62.                 this.products = products;  
  63.                 Console.WriteLine("Produce: {0}", products);  
  64.                 enableGet = true;  
  65.                 Monitor.Pulse(this);  
  66.             }  
  67.         }  
  68.     }  
  69.   
  70.     public class Producer  
  71.     {  
  72.         ProductClass aProductClass;  
  73.         int produceTimes = 1;  
  74.   
  75.         public Producer(ProductClass aProductClass, int produceTimes)  
  76.         {  
  77.             this.aProductClass = aProductClass;  
  78.             this.produceTimes = produceTimes;  
  79.         }  
  80.   
  81.         public void ThreadRun()  
  82.         {  
  83.             for (int i = 0; i < produceTimes; i++)  
  84.             {  
  85.                 aProductClass.ProduceProducts(i);  
  86.             }  
  87.         }  
  88.     }  
  89.   
  90.     public class Consumer  
  91.     {  
  92.         ProductClass aProductClass;  
  93.         int getProductTimes = 1;  
  94.   
  95.         public Consumer(ProductClass aProductClass, int getProductTimes)  
  96.         {  
  97.             this.aProductClass = aProductClass;  
  98.             this.getProductTimes = getProductTimes;  
  99.         }  
  100.   
  101.         public void ThreadRun()  
  102.         {  
  103.             int returnValue;  
  104.             for (int i = 0; i < getProductTimes; i++)  
  105.             {  
  106.                 returnValue = aProductClass.GetProducts();  
  107.             }  
  108.         }  
  109.     }  
  110.   
  111.     class Program  
  112.     {  
  113.         static void Main(string[] args)  
  114.         {  
  115.             ProductClass aProductClass = new ProductClass();  
  116.             Producer aProducer = new Producer(aProductClass, 20);  
  117.             Consumer aConsumer = new Consumer(aProductClass, 20);  
  118.   
  119.             Thread produceThread = new Thread(new ThreadStart(aProducer.ThreadRun));  
  120.             Thread consumeThread = new Thread(new ThreadStart(aConsumer.ThreadRun));  
  121.   
  122.             try  
  123.             {  
  124.                 produceThread.Start();  
  125.                 consumeThread.Start();  
  126.                 produceThread.Join();  
  127.                 consumeThread.Join();  
  128.                 Console.ReadLine();  
  129.             }  
  130.             catch (ThreadStateException ex)  
  131.             {  
  132.                 Console.WriteLine("[ThreadStateException Error]: " + ex.ToString());  
  133.             }  
  134.             catch (ThreadInterruptedException ex)  
  135.             {  
  136.                 Console.WriteLine("[ThreadInterruptedException Error]: " + ex.ToString());  
  137.             }  
  138.         }  
  139.     }  
  140. }  
0 0
原创粉丝点击