码迷,mamicode.com
首页 > 其他好文 > 详细

Semaphore(信号量)

时间:2016-01-11 20:11:42      阅读:122      评论:0      收藏:0      [点我收藏+]

标签:

  场景:当多个任务或线程并行运行时,难以避免的对某些有限的资源进行并发的访问

 

  可以考虑使用信号量来进行这方面的控制(System.Threading.Semaphore)是表示一个Windows内核的信号量对象(操作系统级别,可以跨进程或AppDomain)。如果预计等待的时间较短,使用SemaphoreSlim(单进程)带来的开销更小。关于两者的区别如下:

  System.Threading.Semaphore 类表示一个命名(系统范围内)或本地信号量。它是环绕 Win32 信号量对象的精简包装器。Win32 信号量是计数信号量,该可用于控制对资源池的访问。

  SemaphoreSlim 类表示一个轻量、快速的信号量,可在等待时间预计很短的情况下用于在单个进程内等待。 SemaphoreSlim 尽可能多地依赖公共语言运行时 (CLR) 提供的同步基元。但是,它还提供延迟初始化、基于内核的等待句柄,作为在多个信号量上进行等待的必要支持。 SemaphoreSlim 也支持使用取消标记,但不支持命名信号量或使用用于同步的等待句柄。


  这里我们只讨论System.Threading.Semaphore,.Net FrameWork中的信号量通过跟踪进入和离开的任务或线程来协调对资源的访问。号量需要知道资源的最大数量,当一个任务进入时,资源计数器会被减1(获取到访问许可证),当计数器为0时,如果有任务访问资源(未被授权访问许可证),它会被阻塞,直到有任务离开为止

  介绍一下Semaphore这个类的常用的初始化构造方法,如下,请仔细阅读注释部分。

   /// <summary>
    /// Initializes a new instance of the <see cref="T:System.Threading.Semaphore"/> class, specifying the maximum number of concurrent entries and optionally reserving some entries.
    /// </summary>
    /// <param name="initialCount">The initial number of requests for the semaphore that can be granted concurrently.</param><param name="maximumCount">The maximum number of requests for the semaphore that can be granted concurrently.</param><exception cref="T:System.ArgumentException"><paramref name="initialCount"/> is greater than <paramref name="maximumCount"/>.</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="maximumCount"/> is less than 1.-or-<paramref name="initialCount"/> is less than 0.</exception>
    [SecuritySafeCritical]
    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    public Semaphore(int initialCount, int maximumCount);

  initialCount:信号量可以接受的并发请求数量的初始值

  maximumCount:信号量可以接受的并发请求数量的最大值

  那么看下面这个demo。

技术分享
 1 class Program
 2     {
 3         //创建一个可授权2个许可证的信号量,且初始值为2
 4         static Semaphore _semaphore = new Semaphore(2, 2);
 5 
 6         static void Main(string[] args)
 7         {
 8             Task.Factory.StartNew(() => DoWork());
 9             Task.Factory.StartNew(() => DoWork());
10             Task.Factory.StartNew(() => DoWork());
11 
12             Console.ReadLine();
13         }
14 
15         static void DoWork()
16         {
17             try
18             {
19                 Console.WriteLine(string.Format("Thread {0} 正在等待一个许可证……", Thread.CurrentThread.ManagedThreadId));
20                 _semaphore.WaitOne();
21                 Console.WriteLine(string.Format("Thread {0} 申请到许可证……", Thread.CurrentThread.ManagedThreadId));
22                 Thread.Sleep(5000);
23                 Console.WriteLine(string.Format("Thread {0} 释放许可证……", Thread.CurrentThread.ManagedThreadId));
24             }
25             finally
26             {
27                 _semaphore.Release();
28             }
29         }
30     }
View Code

  多个线程申请获取许可证,其中线程A通过_semaphore.WaitOne拿到了一个许可证,进行initialCount-1操作,业务完成之后再调用_semaphore.Release释放了这个许可证,initialCount+1。如果设置最大并发数=1,那么当前仅有1个线程能够拿到这个许可,其他线程都处于阻塞状态,直到该线程释放为止。当然信号量不可能永久的阻塞在那里。信号量也提供了超时处理机制。方法是在Wait函数中传入一个超时等待时间 - Wait(int TIMEOUT)。当Wait返回值为false时表明它超时了。如果传入了 -1,则表示无限期的等待。

  关于信号量和锁/队列的概念

  信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,也是操作系统用来控制等待一种机制 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。
  互斥量(Mutex) ,互斥量表现互斥现象的数据结构,也被当作二元信号灯。一个互斥基本上是一个多任务敏感的二元信号,它能用作同步多任务的行为,它常用作保护从中断来的临界段代码并且在共享同步使用的资源。
Mutex本质上说就是一把锁,提供对资源的独占访问,所以Mutex主要的作用是用于互斥。Mutex对象的值,只有0和1两个值。这两个值也分别代表了Mutex的两种状态。值为0, 表示锁定状态,当前对象被锁定,用户进程/线程如果试图Lock临界资源,则进入排队等待;值为1,表示空闲状态,当前对象为空闲,用户进程/线程可以Lock临界资源,之后Mutex值减1变为0。
  Enqueue和Lock实际上是一个事物的两个名字。他们都支持队列(queue)和并发(concurrency)。他们在队列中的管理方式是“先进先出”(FIFO)的方式。

 

Semaphore(信号量)

标签:

原文地址:http://www.cnblogs.com/Mushrooms/p/5122187.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!