[.net 多线程]Semaphore信号量

  信号量(Semaphore)是一种CLR中的内核同步对象。与标准的排他锁对象(Monitor,Mutex,SpinLock)不同的是,它不是一个排他的锁对象,它与SemaphoreSlim,ReaderWriteLock等一样允许多个有限的线程同时访问共享内存资源。Semaphore就好像一个栅栏,有一定的容量,当里面的线程数量到达设置的最大值时候,就没有线程可以进去。然后,如果一个线程工作完成以后出来了,那下一个线程就可以进去了。Semaphore的WaitOne或Release等操作分别将自动地递减或者递增信号量的当前计数值。当线程试图对计数值已经为0的信号量执行WaitOne操作时,线程将阻塞直到计数值大于0。

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

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

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

Semaphore的WaitOne或者Release方法的调用大约会耗费1微秒的系统时间,而优化后的SemaphoreSlim则需要大致四分之一微秒。在计算中大量频繁使用它的时候SemaphoreSlim还是优势明显,所以在4.0以后的多线程开发中,推荐使用SemaphoreSlim。

在构造Semaphore时,最少需要2个参数。信号量的初始容量和最大的容量。

[SecuritySafeCritical]
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public Semaphore(int initialCount, int maximumCount);
Semaphore

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

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

 

示例代码:

 1 using System;
 2 using System.Threading;
 3 using System.Threading.Tasks;
 4 
 5 public class Example
 6 {
 7     private static SemaphoreSlim semaphore;
 8     // A padding interval to make the output more orderly.
 9     private static int padding;
10 
11     public static void Main()
12     {
13         // Create the semaphore.
14         semaphore = new SemaphoreSlim(0, 3);
15         Console.WriteLine("{0} tasks can enter the semaphore.",
16                           semaphore.CurrentCount);
17         Task[] tasks = new Task[5];
18 
19         // Create and start five numbered tasks.
20         for(int i = 0; i <= 4; i++)
21         {
22             tasks[i] = Task.Run( () => {
23             // Each task begins by requesting the semaphore.
24             Console.WriteLine("Task {0} begins and waits for the semaphore.",
25                               Task.CurrentId);
26             semaphore.Wait();
27 
28             Interlocked.Add(ref padding, 100);
29 
30             Console.WriteLine("Task {0} enters the semaphore.", Task.CurrentId);
31 
32             // The task just sleeps for 1+ seconds.
33             Thread.Sleep(1000 + padding);
34 
35             Console.WriteLine("Task {0} releases the semaphore; previous count: {1}.",
36                               Task.CurrentId, semaphore.Release()); } );
37         }
38 
39         // Wait for half a second, to allow all the tasks to start and block.
40         Thread.Sleep(500);
41 
42         // Restore the semaphore count to its maximum value.
43         Console.Write("Main thread calls Release(3) --> ");
44         semaphore.Release(3);
45         Console.WriteLine("{0} tasks can enter the semaphore.",
46                           semaphore.CurrentCount);
47         // Main thread waits for the tasks to complete.
48         Task.WaitAll(tasks);
49 
50         Console.WriteLine("Main thread exits.");
51     }
52 }
53 // The example displays output like the following:
54 //       0 tasks can enter the semaphore.
55 //       Task 1 begins and waits for the semaphore.
56 //       Task 5 begins and waits for the semaphore.
57 //       Task 2 begins and waits for the semaphore.
58 //       Task 4 begins and waits for the semaphore.
59 //       Task 3 begins and waits for the semaphore.
60 //       Main thread calls Release(3) --> 3 tasks can enter the semaphore.
61 //       Task 4 enters the semaphore.
62 //       Task 1 enters the semaphore.
63 //       Task 3 enters the semaphore.
64 //       Task 4 releases the semaphore; previous count: 0.
65 //       Task 2 enters the semaphore.
66 //       Task 1 releases the semaphore; previous count: 0.
67 //       Task 3 releases the semaphore; previous count: 0.
68 //       Task 5 enters the semaphore.
69 //       Task 2 releases the semaphore; previous count: 1.
70 //       Task 5 releases the semaphore; previous count: 2.
71 //       Main thread exits.
SemaphoreSlim示例

 

Samaphore实现:https://blog.csdn.net/ma_jiang/article/details/78631038

posted on 2018-05-07 23:20  DeeperMiner  阅读(295)  评论(0编辑  收藏  举报

导航