首页 > 其他分享 >Semaphore 和 CountdownEvent 的使用总结

Semaphore 和 CountdownEvent 的使用总结

时间:2023-11-06 22:57:57浏览次数:34  
标签:总结 调用 CountdownEvent CountDownEvent 信号量 线程 Semaphore

信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量。一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。本文主要介绍.NET(C#) 中Semaphore 和 CountdownEvent 的使用。

Semaphore 和 CountdownEvent的使用

1)Semaphore

Semaphore 限制可同时访问某一资源或资源池的线程数。.NET中的信号量(Semaphore)是操作系统维持的一个整数。当整数位0时。其他线程无法进入。当整数大于0时,线程可以进入。每当一个线程进入,整数-1,线程退出后整数+1。整数不能超过信号量的最大请求数。信号量在初始化的时候可以指定这个整数的初始值。System.Threading.Semaphore类的构造函数的两个参数第一个就是信号量的内部整数初始值,也就是初始请求数,第二个参数就是最大请求数。

2)CountdownEvent

System.Threading.CountdownEvent 是在收到信号特定次数后取消阻止等待线程的同步基元。 CountdownEvent 适用于以下情况:不得不先使用 ManualResetEvent 或 ManualResetEventSlim 并手动递减变量,然后再向事件发出信号。 CountdownEvent 表示在计数变为0时处于有信号状态的同步基元,通过信号机制CountdownEvent当有新的需要同步的任务产生时,就调用AddCount增加它的计数,当有任务到达同步点是,就调用Signal函数减小它的计数,当CountdownEvent的计数为零时,就表示所有需要同步的任务已经完成。CountDownEvent与Barrier相似,所不同的是,CountDownEvent调用成员函数Wait()将阻塞,直至成员函数Signal() 被调用达特定的次数,这时CountDownEvent称作就绪态,对于处于就绪态的CountDownEvent,调用Wait()函数将不会再阻塞,只有手动调用Reset()函数后,调用Wait()函数将再次阻塞。CountDownEvent可以通过TryAddCount()AddCount()函数来增加函数Signal() 需被调用的次数,但只有当CountDownEvent处于未就绪态时才会成功。否则根据调用函数的不同,将有可能抛出异常。

Semaphore的使用

.NET中的信号量(Semaphore)是操作系统维持的一个整数。当整数位0时。其他线程无法进入。当整数大于0时,线程可以进入。每当一个线程进入,整数-1,线程退出后整数+1。整数不能超过信号量的最大请求数。信号量在初始化的时候可以指定这个整数的初始值。System.Threading.Semaphore类的构造函数的两个参数第一个就是信号量的内部整数初始值,也就是初始请求数,第二个参数就是最大请求数。

using System;
using System.Threading;
namespace ConsoleApplication
{
    class Program
    {
        // 一个模拟有限资源池的信号量。
        //
        private static Semaphore _pool;
        // 填充Thread.Sleep()间隔,使输出更有序。
        private static int _padding;
        public static void Main()
        {
            //创建一个信号量,这个信号量最多可以满足三个信号量
            //并发请求。初始计数为0,
            //整个信号量计数是初始的
            //主程序线程拥有。
            //
            _pool = new Semaphore(0, 3);

            // 创建并启动五个线程。
            //
            for (int i = 1; i <= 5; i++)
            {
                Thread t = new Thread(new ParameterizedThreadStart(Worker));

                // 启动线程,传递编号。
                t.Start(i);
            }

            //等待半秒钟,让所有的线程启动和阻塞信号量。
            Thread.Sleep(500);

            //主线程开始持有整个信号量计数。
            // 调用Release(3)带来返回信号量的最大值允许等待的线程进入信号量,一次最多3个。
            Console.WriteLine("主线程调用 Release(3)");
            _pool.Release(3);

            Console.WriteLine("主线程退出");
            Console.ReadKey();
        }

        private static void Worker(object num)
        {
            //每个工作线程开始请求信号量
            Console.WriteLine("Thread {0} 开始 " +
                "等待信号量", num);
            _pool.WaitOne();
            // 填充Thread.Sleep()间隔,使输出更有序。
            int padding = Interlocked.Add(ref _padding, 100);
            Console.WriteLine("Thread {0} 进入信号量", num);
            Thread.Sleep(1000 + padding);
            Console.WriteLine("Thread {0} releases the semaphore.", num);
            Console.WriteLine("Thread {0} 之前的信号量计数: {1}",
                num, _pool.Release());
        }
    }

}

3、CountdownEvent的使用

CountDownEvent调用成员函数Wait()将阻塞,直至成员函数Signal()被调用达特定的次数,这时CountDownEvent称作就绪态,对于处于就绪态的CountDownEvent,调用Wait()函数将不会再阻塞,只有手动调用Reset()函数后,调用Wait()函数将再次阻塞。CountDownEvent可以通过TryAddCount()AddCount()函数来增加函数Signal()需被调用的次数,但只有当CountDownEvent处于未就绪态时才会成功。否则根据调用函数的不同,将有可能抛出异常。

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication
{
    class Program
    {
        static CountdownEvent _count = new CountdownEvent(3);
        static void Main(string[] args)
        {
            Task.Factory.StartNew(() =>
            {

                Thread.Sleep(500);
                Console.WriteLine("thread 1 complete");
                _count.Signal();

            });

            Task.Factory.StartNew(() =>
            {

                Thread.Sleep(1000);
                Console.WriteLine("thread 2 complete");
                _count.Signal();

            });

            Task.Factory.StartNew(() =>
            {

                Thread.Sleep(2000);
                Console.WriteLine("thread 3 complete");
                _count.Signal();

            });

            //_count.AddCount();//调用AddCount增加计数
            Console.WriteLine("waiting tasks....");
            _count.Wait();
            Console.WriteLine("all task completed");


            Console.ReadKey();
        }
    }
}

 

标签:总结,调用,CountdownEvent,CountDownEvent,信号量,线程,Semaphore
From: https://www.cnblogs.com/wwkk/p/17813980.html

相关文章

  • 每日总结
    今日收获将图书馆借来的书籍还回去了;写完了人机交互的2/3的作业;联系平台上学习比赛的相关练习题目;真的,以后谁给我发那种格式不规范的!我们就绝交!!!绝交!明天预计学习新的知识,继续进步;继续练习题目;......
  • 11.6每日总结
    相关的易混淆概念 四个阶段1、初始:建立系统业务模型,确定项目边界;2、细化/精化:分析问题领域,建立完善的架构,淘汰高风险元素;3、构建:开发功能,集成产品;4、移交:确保软件可用;六个等级1、未完成级:过程域的一个或者多个特定目标没有被满足;2、已执行级:过程通过转化可识别的工作......
  • 助教工作10月总结(前端开发技术)
    一、助教工作的具体职责和任务作为前端这门课程的助教主要的职责是辅助老师完成在课外的一些教学任务例如 1、课下的疑难解答 :课下辅导中,我通过QQ私聊等方式与学生进行沟通,并帮助他们解决在学习过程中遇到的困惑和问题。我会提供适当的指导和建议,引导学生找到解决问题的方法和......
  • 20231106学习总结ini文件读写
    INI(Initialization)文件是一种常见的配置文件格式,通常用于存储应用程序的配置信息。INI文件通常包含一系列的节(sections)和键-值对(key-valuepairs)。每个节包含一组相关的键-值对。;这是注释[Database]Server=localhostPort=3306Username=myuserPassword=mypassword......
  • NOIP2023模拟12联测33 总结
    NOIP2023模拟12联测33总结目录NOIP2023模拟12联测33总结比赛过程正解A.构造题目大意思路思路B.游戏题目大意思路C.数数题目大意D.滈葕题目大意思路总结比赛过程先看了一眼\(T1\),发现又是恶心构造题,果断跳过。\(T2\)期望题,这么恶心吗,果断跳过。看看\(T3\)发现好像有......
  • 每日总结20231106
    代码时间(包括上课)3h代码量(行):100行博客数量(篇):1篇相关事项:1、今天是周一,一周里面最困的一天,但是今天没有迟到呦,今天第一节课是软件设计模式,写的是适配器模式和桥接模式,这次还很简单,是自己写的。2、今天第二节课上的是人机交互技术,看了相关C#的相关知识点的视频。3、今天晚上打......
  • 【Redis使用手册】一年多来redis使用markdow笔记总结,第(2)篇:Redis命令操作详解
    Redis是一个高性能的key-value数据库。本文会让你知道:什么是nosql、Redis的特点、如何修改常用Redis配置、写出Redis中string类型数据的增删改查操作命令、写出Redis中hash类型数据的增删改查相关命令、说出Redis中list保存的数据类型、使用StrictRedis对象对string类型数据......
  • 2023.10月-助教总结报告
    一、助教工作的具体职责和任务 老师QQ通知,让我去办公室。到了办公室后,老师线下交代注意事项以及需要做的事情,并把材料拿给我。建立班级的QQ群,通知学生事情,,核对进群同学身份。云班课老师授予了助教权限,跟随课程,这个月第一部分课程结束,给同学们出第一部分作业的题目,并写出答案,包括......
  • 大数据学习每日总结-第三天
    今天重点学习了hive数据仓库,了解了数据仓库这个新的概念,以及它于关系型数据库的区别。Hive数据仓库一款基于Hadoop的仓库,它依赖于Hadoop上的各种工具,同时又又将Hadoop存储的数据和表相联系,使得用户可以通过sql语言来操作Hadoop中的数据。今天我着重学习了hive数据库的一些sql操作......
  • 2023.11.6——每日总结
    学习所花时间(包括上课):9h代码量(行):0行博客量(篇):1篇今天,上午学习,下午学习;我了解到的知识点:1.软考知识明日计划:学习......