c#线程同步使用详解示例

这篇文章主要介绍了c#线程同步使用方法,介绍几种常用的C#进行线程同步的方式,需要的朋友可以参考下

在应用程序中使用多个线程的一个好处是每个线程都可以异步执行。对于 Windows 应用程序,耗时的任务可以在后台执行,而使应用程序窗口和控件保持响应。对于服务器应用程序,多线程处理提供了用不同线程处理每个传入请求的能力。否则,在完全满足前一个请求之前,将无法处理每个新请求。然而,线程的异步特性意味着必须协调对资源(如文件句柄、网络连接和内存)的访问。否则,两个或更多的线程可能在同一时间访问相同的资源,而每个线程都不知道其他线程的操作。

线程同步的方式

线程同步有:临界区、互斥区、事件、信号量四种方式
临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、事件(Event)的区别
1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。
2、互斥量:采用互斥对象机制。 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享
3、信号量:它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目
4、事 件: 通过通知操作的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较的操作

C#中常见线程同步方法

我们介绍几种常用的C#进行线程同步的方式,这些方式可以根据其原理,找到对应上面的四种类型之一。

1、Interlocked
为多个线程共享的变量提供原子操作。

根据经验,那些需要在多线程情况下被保护的资源通常是整型值,且这些整型值在多线程下最常见的操作就是递增、递减或相加操作。Interlocked类提供了一个专门的机制用于完成这些特定的操作。这个类提供了Increment、Decrement、Add静态方法用于对int或long型变量的递增、递减或相加操作。此类的方法可以防止可能在下列情况发生的错误:计划程序在某个线程正在更新可由其他线程访问的变量时切换上下文;或者当两个线程在不同的处理器上并发执行时。 此类的成员不引发异常。

Increment和Decrement方法递增或递减变量并将结果值存储在单个操作中。 在大多数计算机上,增加变量操作不是一个原子操作,需要执行下列步骤:

1)将实例变量中的值加载到寄存器中。
2)增加或减少该值。
3)在实例变量中存储该值。
如果不使用 Increment 和 Decrement,线程会在执行完前两个步骤后被抢先。 然后由另一个线程执行所有三个步骤。 当第一个线程重新开始执行时,它覆盖实例变量中的值,造成第二个线程执行增减操作的结果丢失。

Exchange 方法自动交换指定变量的值。 CompareExchange 方法组合了两个操作:比较两个值以及根据比较的结果将第三个值存储在其中一个变量中。 比较和交换操作按原子操作执行。

案例分析:共享打印机。

通常我们会使用共享打印机,几台计算机共享一台打印机,每台计算机可以发出打印指令,可能会出现并发情况。当然我们知道,打印机采用了队列技术。为了简化操作,我们假定,在打印机收到命令时,即可打印,而且在同一时间只能有一个打印任务在执行。我们使用Interlocked方法来实现多线程同步。具体代码如下:

复制代码 代码如下:

using System;
using System.Threading;

namespace MutiThreadSample.ThreadSynchronization
{
    class PrinterWithInterlockTest
    {
   ///


   /// 正在使用的打印机
   /// 0代表未使用,1代表正在使用
   ///

   public static int UsingPrinter = 0;
   ///
   /// 计算机数量
   ///

   public static readonly int ComputerCount = 3;
   ///
   /// 测试
   ///

   public static void TestPrint()
   {
  Thread thread;
  Random random = new Random();
  for (int i = 0; i   {
 thread = new Thread(MyThreadProc);
 thread.Name = string.Format("Thread{0}",i);
 Thread.Sleep(random.Next(3));
 thread.Start();
  }
   }
   ///
   /// 线程执行操作
   ///

   private static void MyThreadProc()
   {
  //使用打印机进行打印
  UsePrinter();
  //当前线程等待1秒
  Thread.Sleep(1000);
   }
   ///
   /// 使用打印机进行打印
   ///

   private static bool UsePrinter()
   {
  //检查大引进是否在使用,如果原始值为0,则为未使用,可以进行打印,否则不能打印,继续等待
  if (0 == Interlocked.Exchange(ref UsingPrinter, 1))
  {
 Console.WriteLine("{0} acquired the lock", Thread.CurrentThread.Name);

 //Code to access a resource that is not thread safe would go here.

 //Simulate some work
 Thread.Sleep(500);

 Console.WriteLine("{0} exiting lock", Thread.CurrentThread.Name);

 //释放打印机
 Interlocked.Exchange(ref UsingPrinter, 0);
 return true;
  }
  else
  {
 Console.WriteLine("   {0} was denied the lock", Thread.CurrentThread.Name);
 return false;
  }
   }

    }
}

以上就是c#线程同步使用详解示例的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » 其他教程