C#之:线程同步 Semaphore类和 SemaphoreSlim类

Semaphore:信号量

命名空间:System.Threading
限制可同时访问某一资源或资源池的线程数。
信号量非常类似于互斥,其区别是信号量可以同时有多个线程使用。信号量是一种计数的互斥锁定。使用信号量,可以定义允许同时访问受保护和锁定的资源的线程个数。如果需要限制可以访问可用资源的线程数量,信号量就很有用。

构造函数

构造函数 描述
Semaphore(Int32, Int32) 初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数。
Semaphore(Int32, Int32, String) 初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数,根据需要指定系统信号灯对象的名称。
Semaphore(Int32, Int32, String, Boolean) 初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数,还可以选择指定系统信号量对象的名称,以及指定一个变量来接收指示是否创建了新系统信号量的值。
Semaphore(Int32, Int32, String, Boolean, SemaphoreSecurity) 初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数,可以选择指定系统信号量对象的名称,指定一个变量来接收指示是否创建了新系统信号量的值,以及指定系统信号量的安全访问控制。

方法

方法 描述
Close() 释放由当前 WaitHandle 占用的所有资源。
Dispose() 释放 WaitHandle 类的当前实例所使用的所有资源。
OpenExisting(String) 打开指定名称为信号量(如果已经存在)。
OpenExisting(String, SemaphoreRights) 用安全访问权限打开指定名称为信号量(如果已经存在)。
Release() 退出信号量并返回前一个计数。
Release(Int32) 以指定的次数退出信号量并返回前一个计数。
WaitOne() 阻止当前线程,直到当前 WaitHandle 收到信号。
WaitOne(Int32) 阻止当前线程,直到当前 WaitHandle 收到信号,同时使用 32 位带符号整数指定时间间隔(以毫秒为单位)。
WaitOne(Int32, Boolean) 阻止当前线程,直到当前的 WaitHandle 收到信号为止,同时使用 32 位带符号整数指定时间间隔,并指定是否在等待之前退出同步域。

属性

属性 描述
Handle 获取或设置本机操作系统句柄。
SafeWaitHandle 获取或设置本机操作系统句柄。

字段

字段 描述
WaitTimeout 指示在任何等待句柄终止之前 WaitAny(WaitHandle[], Int32, Boolean) 操作已超时。 此字段为常数。

具体详细信息请点击微软官方链接:Semaphore

示例:

 static void Main(string[] args)
        {
            int taskCount = 6;
            int semaphoreCount = 3;
            var semaphore = new Semaphore(semaphoreCount, semaphoreCount);
            var tasks = new Task[taskCount];
            for (int i = 0; i < taskCount; i++)
            {
                tasks[i] = Task.Run(() => TaskRuning(semaphore));
            }
            Task.WaitAll(tasks);
            Console.WriteLine("所有任务以完成!");

            Console.ReadKey();
        }

        static void TaskRuning(Semaphore s)
        {
            bool isCompleted = false;
            while(!isCompleted)
            {
                if(s.WaitOne(600))
                {
                    try
                    {
                        Console.WriteLine("Task {0} 锁定这个信号",Task.CurrentId);
                        Thread.Sleep(1000);
                    }
                    finally
                    {
                        Console.WriteLine("Task {0} 释放这个信号", Task.CurrentId);
                        s.Release();
                        isCompleted = true;
                    }
                }
                else
                {
                    Console.WriteLine("超时任务 :Task {0} 等待下一次",Task.CurrentId);
                }
            }
        }

运行输出:
C#之:线程同步 Semaphore类和 SemaphoreSlim类_第1张图片
示例说明:
创建了6个任务和一个计数为3的信号量。在 Semaphore类的构造函数中,定义了锁定个数的计数为3(可以同时授予的信号量的最大请求数),它是信号量构造函数的第二个参数来获得。还定义了最初释放的锁定数(最大并发入口数,构造函数第一个参数)。如果第一个参数值小于第二个参数值,它们的差就是已经分配线程的计数值。可以理解为:第一个参数为剩余机会数,第二个参数为总的机会数。第一个参数必须小于或等于第二个参数。

与互斥锁一样,也可 以给信号量指定名称,使之在不同之间的进程共享。这里没有指定名称,所以只能在当前进程中使用。程序启动 创建 Semaphore对象,启动6个任务,都给相同的信号量。然后开始异常执行任务。但是每次只能进去3个线程的任务。其他要等待前面的任务释放信号后再依次进入。
**信号量控制的只是线程同步的量,而不管顺序。**这个例子来说线程控制的就是线程同步量为3,也就是同时并发的线程数量为3个,至于是哪个先哪个后不是由这里的信号量决定的。

SemaphoreSlim类 是对较短等待时间进行优化的轻型版本,用法类似,感兴趣的可以自己试一下。

你可能感兴趣的:(C#,多线程,并行和异步)