首页 > 其他分享 >【.NET深呼吸】线程信号量(Semaphore)

【.NET深呼吸】线程信号量(Semaphore)

时间:2024-05-27 22:12:09浏览次数:25  
标签:信号量 访问 任务 线程 Semaphore Release NET

Semaphore类可以控制某个资源允许访问的线程数,Semaphore有命名式的,也有不命名的;如果不考虑跨进程工作,一般在代码中使用不命名方式即可。

信号量有点类似于等待句柄,某个线程如果调用了WaitOne方法,这个线程就会暂停,并且等待有可用的信号量时才会继续执行;某个线程调用Release方法,就会释放一个信号计数值,每调用一次就释放一个,如果想一次性释放N个信号,可以调用Release(int)重载,把要释放的数量传递给方法参数,但这个数值不能超过Semaphore实例化时所指定的最大值,否则会引发异常。

Semaphore构造函数可以指定允许的最大信号量,以及默认的信号量。声明如下:

Semaphore(int initialCount, int maximumCount);

maximumCount参数指定该对象允许的最大信号量;initialCount参数指定默认值,这个默认值不能超过maximumCount指定的最大值。即该Semaphore实例默认允许多少个线程收到信号(访问资源)。

当某个占用资源的线程调用Release方法后,它会释放出一个或多个信号,这时候,其他等待的线程就可以继续执行。

 

只要是涉及到线程问题都特别难说清楚,相当抽象,相当考验人的理解能力。

比如,图书馆里面有五本《X瓶梅》,但想借这本书的有20人。前面五个人自然很轻松就借到(进入访问圈,这五个线程以外的线程等待),其他人只好等了。

过了几天后,有个家伙通宵看书,终于看完了,因此他还了书,这时候,剩下的15个人看谁的动作快,可以借到刚还回去的这本书。

再过了几天,又有两个人看完了,还书。此时,剩下的14个人中,有两个人可以借得此书。

 

大概的原理就是这样,下面看看例子。

复制代码
    class Program
    {
        // 生成随机数,以延迟每个任务的执行时间
        static Random rand = new Random();
        // 声明Semaphore变量,以控制线程信号量
        static Semaphore sm = null;
        static void Main(string[] args)
        {
            sm = new Semaphore(1, 4); //实例化
            // 启动10个任务
            for (int i = 0; i < 10; i++)
            {
                Task t = new Task(DoWork, "任务" + (i + 1));
                t.Start();
            }

            // 防止DOS窗口立即退出
            Console.Read();
        }

        private static async void DoWork(object p)
        {
            sm.WaitOne(); //等待花开
            string tn = p?.ToString();
            Console.WriteLine($"{tn} 已获得访问。");
            await Task.Delay(rand.Next(1, 10) * 1000);
            // 释放
            sm.Release(); //花谢了
            Console.WriteLine($"{tn}已释放。");
        }
    }
复制代码

 

多线程开发我最喜欢用Task类,方便简单强大好用高大上,而且它还能自行处理CPU多个核的问题。在上面例子中,有10个任务要执行,但我所实例化的Semaphore对象给的最大访问线程数为4,而默认状态下只允许1个线程同时访问。

所以,10个任务启动后,其中一个会抢到访问权,其他任务就等吧。这时候Semaphore对象可访问数为0。因为默认只允许1,现在有一个线程抢了,所以剩下就是0个访问权了。

当这个抢到访问权的任务调用Release方法后,访问权被释放,这时候剩下的9个任务就开始抢,谁抢到谁就执行……依此类推。

 

看看运行结果。

 

任务1手快,它先抢到了访问权,于是它dododo,do完后,调用Release方法释放,然后任务3人品好,就抢到了访问权,然后XXXXX,X完后调用Release释放。其他线程继续抢……

 

估计看完以上例子后,大家应该有点头绪了。

现在,我们把上面的代码改一下,在初始化Semaphore对象时的默认值从1改为3。

sm = new Semaphore(3, 4);

默认允许3个线程同时访问资源,最大数量为4。

然后再次运行,结果如下:

 

因为默认允许3个线程同时进入,所以在输出结果中,前面三个任务都能获取访问权,而其他的任务只能等待机会。当前面已获得资源的三个任务中有一个或者N个进行释放后,剩下的任务又开始抢机会。

 

本文示例下载地址:https://files.cnblogs.com/files/tcjiaan/DemoApp.zip

 

  分类: 个人文章 标签: 线程 , 信号量    

标签:信号量,访问,任务,线程,Semaphore,Release,NET
From: https://www.cnblogs.com/webenh/p/18216665

相关文章

  • .NET8极致性能优化AOT
    前言.NET8对于性能的优化是方方面面的,所以AOT预编译机器码也是不例外的。本篇来看下对于AOT的优化。原文:.NET8极致性能优化AOT详述首先明确一个概念,.NET里面的AOT它是原生的。什么意思呢?也就是说通过ILC编译器(AOT编译器,参考:.Net7新编译器ILC简析)编译出来的代码是各个平......
  • 在 Inno Setup 中检测 .NET 5 / .NET Core 运行环境是否存在
    为了将.NET5/.NETCore应用程序部署到客户机,我们可以编写InnoSetup代码来判断客户机是否安装了必要的运行环境。.NET官方仓库 中提供了一个名为 NetCoreCheck 的项目,可以用于检测指定的.NET5/.NETCore环境是否存在。编译好的文件可以从以下两个地址下载:文件......
  • 通过 .NET NativeAOT 实现用户体验升级
    前言#TypedocConverter 是我先前因帮助维护monaco-editor-uwp但苦于monacoeditor的API实在太多,手写C#的类型绑定十分不划算而发起的一个项目。这个工具可以将typedoc根据TypeScript生成的JSON文件直接生成对应的C#类型绑定代码,并提供完整的JSON序列化支持,......
  • .NET 将多个程序集合并成单一程序集的 4+3 种方法
       将.NET程序集与依赖合并到一起的方法有下面四种:使用.NETCore3.0自带的PublishSingleFile属性合并依赖使用Fody使用SourceYard源代码包使用ILMerge(微软所写)或者ILRepack(基于Mono.Ceil)————————————————版权声......
  • POSEIDON: Privacy-Preserving Federated NeuralNetwork Learning
    写在最前面,感觉这一篇的技术更贴近于密码学,所以部分核心技术读起来比较吃力。仅供大家参考哇~Abstract—Inthispaper,weaddresstheproblemofprivacypreservingtrainingandevaluationofneuralnetworksinanN-party,federatedlearningsetting.Weproposea......
  • 鸿蒙HarmonyOS实战-Stage模型(线程模型)
    ......
  • Kubernetes(k8s) v1.30.1 本地集群部署 安装metallb 支持LoadBalancer 生产环境 推荐
    1 metallb安装参考:Kubernetes(k8s)v1.30.1本地集群部署默认不支持LoadBalancermetallb来解决-CSDN博客2 删除Layer2模式配置kubectldelete-fIPAddressPool.yamlkubectldelete-fL2Advertisement.yamlkubectldelete-fdiscuz-srv.yaml3配置k8sMeta......
  • .NET 7 AOT 的使用以及 .NET 与 Go 互相调用
    目录背景C#部分环境要求创建一个控制台项目体验AOT编译C#调用库函数减少体积C#导出函数C#调用C#生成的AOTGolang部分安装GCCGolang导出函数.NETC#和Golang互调C#调用GolangGolang调用C#其他 背景其实,规划这篇文章有一段时......
  • dotnet c# samples core nativeaot NativeLibrary
     如何在System.Text.Json中使用源生成 https://learn.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json/source-generation?pivots=dotnet-8-0 https://github.com/dotnet/samples/tree/main/core/nativeaot/NativeLibrary   ......
  • 详解PySide多线程【Python-Pyside图形界面绘制#2】
    在了解pyside多线程之前,如果是初学者可以先去看看我的第一篇文章《超详细实例详解Python多线程》,文中有对多线程的概念进行详细介绍,如果有相关基础可直接跳过。【Python】超详细实例讲解python多线程(threading模块)_pythonthreading介绍-CSDN博客https://blog.csdn.net/Xiao_......