zoukankan      html  css  js  c++  java
  • [.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

  • 相关阅读:
    个人学习jQuery笔记
    (转载) jQuery页面加载初始化的3种方法
    [转]学会和同事相处的30个原则
    解决iis出现这个问题-2147467259 (0x80004005)
    不规则瀑布流图片墙
    实现图片大小的自动控制( 图片大小控制CSS代码)
    (转载)DataTable使用技巧总结
    (转载) jQuery 页面加载初始化的方法有3种
    ajax连接数据库并操作数据库
    java Semaphore实现ABC三个线程循环打印
  • 原文地址:https://www.cnblogs.com/deepminer/p/9005726.html
Copyright © 2011-2022 走看看