C# dotnet 的锁 SemaphoreSlim 和队列
本文主要是试验在顺序进入等待 SemaphoreSlim 的任务是否会按照顺序经过锁执行
我在一个有趣的WPF程序里面,需要限制任务同时执行的线程数量,不然用户就会说用我的程序会让电脑卡渣。而我的任务是需要按照指定顺序执行的,我需要每次同时仅执行10个任务,同时任务执行按照传入的顺序
此时可以用到 SemaphoreSlim 这个类,这个类的作用如下,给定初始的可以通过锁的数量,以及这个最大可以通过锁的数量。通过 Wait 方法进行等待,如果当前已经有超过可以通过的任务通过了,那么在 Wait 方法将会阻塞。如果没有超过可以通过的数量,那么将可以通过
使用 Release 方法可以添加一个或多个可以通过的数量,但是可以通过的数量最大不会超过初始化时传入的最大可以通过锁的数量的值
如下面代码
var semaphoreSlim = new SemaphoreSlim(10, 20);
此时表示初始化的时候,可以让 10 个任务通过锁,也就是初始化的时候可以有10次调用 Wait 方法能通过
而第二个参数表示最大的可以通过的数量,通过 Release 可以添加一个或多个可以通过锁的任务,如 semaphoreSlim.Release(100); 表示设置有 100 个可以通过锁的任务,但是实际上在上面代码里面,因为设置了最大值是 20 也就是即使写 100 其实之后能通过的任务只有 20 个
而本文的测试在于我有任务按照顺序调用 Wait 方法进入等待,如我的任务有序号,我按照任务1 任务2 任务3 的顺序调用Wait方法,同时此时的锁的可以通过的数量是 0 也就是所有任务在等待
之后我通过 Release 方法的不断调用,请问此时通过锁的任务是否和队列一样,先等待的任务就先通过锁。答案是这样的
先调用 Wait 方法的任务,在锁开始释放的时候就先通过,我通过一个有趣的代码用来测试
我需要有很多线程进入锁的 Wait 方法,但是这些线程每个线程是一个任务,这些任务有顺序,进入等待方法的时候按照顺序进入
而小伙伴都知道,创建线程的先后顺序不会等于线程执行的先后顺序,所以我使用了 AutoResetEvent 在线程创建然后执行开始之后再创建下一个线程
先通过 SemaphoreSlim 创建一个初始值是 10 而最大值是 10 的锁,然后创建一个 AutoResetEvent 设置默认能通过一次
var semaphoreSlim = new SemaphoreSlim(10, 10);
private static readonly AutoResetEvent _autoResetEvent = new AutoResetEvent(true);
接下来进入循环创建线程,创建线程的时候先等待 AutoResetEvent 锁,而在线程执行的时候释放 AutoResetEvent 锁,这样就能让线程一定是在上一个线程执行之后再创建。而设置 AutoResetEvent 的初始值是通过,也就是第一个线程可以创建,但第二个线程需要等待第一个线程开始执行再创建
for (int i = 0; i < 1000; i++)
{
var n = i;
_autoResetEvent.WaitOne();
new Thread(() => { GeregelkunoNeawhikarcee(semaphoreSlim, n); }).Start();
}
添加 GeregelkunoNeawhikarcee 方法,在方法进入的时候,也就是线程开始执行,释放 AutoResetEvent 锁,这样就能让下一个线程创建
_autoResetEvent.Set();
进入等待 SemaphoreSlim 此时等待是按照线程创建的顺序等待
semaphoreSlim.Wait();
接下来输出当前的任务号,主要用来调试是否通过锁的顺序和线程进入等待的顺序相同
Console.WriteLine(n);
接下来通过 Thread.Sleep 模拟执行长任务
在任务执行完成之后释放锁让下一个任务开始,全部代码放在这里
static void Main(string[] args)
{
var semaphoreSlim = new SemaphoreSlim(10, 10);
for (int i = 0; i < 1000; i++)
{
var n = i;
_autoResetEvent.WaitOne();
new Thread(() => { GeregelkunoNeawhikarcee(semaphoreSlim, n); }).Start();
}
Console.Read();
}
private static readonly AutoResetEvent _autoResetEvent = new AutoResetEvent(true);
private static void GeregelkunoNeawhikarcee(SemaphoreSlim semaphoreSlim, int n)
{
Console.WriteLine($"{n} 进入");
_autoResetEvent.Set();
semaphoreSlim.Wait();
Console.WriteLine(n);
Thread.Sleep(TimeSpan.FromSeconds(1));
semaphoreSlim.Release();
}
可以看到代码是按照顺序输出的
本文代码放在github欢迎小伙伴访问

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
C# dotnet 的锁 SemaphoreSlim 和队列的更多相关文章
- 4、网络并发编程--僵尸进程、孤儿进程、守护进程、互斥锁、消息队列、IPC机制、生产者消费者模型、线程理论与实操
昨日内容回顾 操作系统发展史 1.穿孔卡片 CPU利用率极低 2.联机批处理系统 CPU效率有所提升 3.脱机批处理系统 CPU效率极大提升(现代计算机雏形) 多道技术(单核CPU) 串行:多个任务依 ...
- redis分布式锁和消息队列
最近博主在看redis的时候发现了两种redis使用方式,与之前redis作为缓存不同,利用的是redis可设置key的有效时间和redis的BRPOP命令. 分布式锁 由于目前一些编程语言,如PHP ...
- python 并发编程 锁 / 信号量 / 事件 / 队列(进程间通信(IPC)) /生产者消费者模式
(1)锁:进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 虽然使用加锁的形式实现了 ...
- 互斥锁,IPC队列
进程同步(锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,part1:共享同一打印终端,发现会有多行内容打印到一行的现象(多个进程共享并抢占同一个 ...
- 4-[多进程]-互斥锁、Queue队列、生产者消费者
1.互斥锁 (1)为什么需要互斥锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如下 #并发运行,效率 ...
- python 锁 信号量 事件 队列
什么是python 进程锁? #同步效率低,但是保证了数据安全 重点 很多时候,我们需要在多个进程中同时写一个文件,如果不加锁机制,就会导致写文件错乱 这个时候,我们可以使用multiprocess ...
- Zookeeper--分布式锁和消息队列
在java并发包中提供了若干锁的实现,它们是用于单个java虚拟机进程中的:而分布式锁能够在一组进程之间提供互斥机制,保证在任何时刻只有一个进程可以持有锁. 分布式环境中多个进程的锁则可以使用Zook ...
- 进击的Python【第九章】:paramiko模块、线程与进程、各种线程锁、queue队列、生产者消费者模型
一.paramiko模块 他是什么东西? paramiko模块是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 先来个实例: import param ...
- GIL全局解释器锁、死锁、递归锁、线程队列
目录 GIL全局解释锁 多线程的作用 测试计算密集型 IO密集型 死锁现象 递归锁 信号量(了解) 线程队列 GIL全局解释锁 GIL本质上是一个互斥锁. GIL是为了阻止同一个进程内多个进程同时执行 ...
- java-spring基于redis单机版(redisTemplate)实现的分布式锁+redis消息队列,可用于秒杀,定时器,高并发,抢购
此教程不涉及整合spring整合redis,可另行查阅资料教程. 代码: RedisLock package com.cashloan.analytics.utils; import org.slf4 ...
随机推荐
- GID:旷视提出全方位的检测模型知识蒸馏 | CVPR 2021
论文提出的GID框架能够自动选择可辨别目标用于知识蒸馏,而且综合了feature-based.relation-based和response-based知识,全方位蒸馏,适用于不同的检测框架中.从实验 ...
- archlinux启动virtualbox实例出现错误:内核驱动未安装
参照 https://cn.linux-console.net/?p=22258 错误如下 Kernel driver not installed (rc=-1908) The VirtualBox ...
- IntelliJ IDEA集成本地Maven步骤
IntelliJ IDEA集成本地Maven步骤 一.前期准备 Maven已经在本地环境配置完成,步骤可以参考我的这篇文章: https://www.cnblogs.com/rainbow-1/p/1 ...
- C++简单实现unique_ptr
唯一指针 管理指针的存储,提供有限的垃圾回收工具,与内置指针相比几乎没有开销(取决于所使用的删除程序). 这些对象具有获取指针所有权的能力:一旦它们获得所有权,它们就会通过在某个时候负责删除指向的对象 ...
- 突然连不上Github或者连接超时的解决办法
问题描述当进行仓库pull或者push时,报错如下(连接失败/被拒绝/超时等): Failed to connect to github.com port 443: Connection refuse ...
- sublime text 笔记
问题: Sublime Text编辑器开启或关闭Vim模式 插件: 使用sublime server启动本地服务器进行调试
- 12 CSS 的float属性
12 CSS 的float属性 流动布局 流动模型(Flow),即文档流,浏览器打开HTML网页时,从上往下,从左往右,逐一加载. 在正常情况下,HTML元素都会根据文档流来分布网页内容的. 文档流有 ...
- #网络流,树状数组#JZOJ 4020 Revolution with JZOJ 4018 Magic
CF297E Mystic Carvings=JZOJ 4018 Magic JZOJ 4020 Revolution 题目 有一个\(n*m(n,m\leq 20)\)的网格图 这格子有收益当且仅当 ...
- #SG函数,记忆化搜索#HDU 4111 Alice and Bob
题目 Alice和Bob两个好朋友又开始玩取石子了. 游戏开始时,有\(n\)堆石子排成一排,然后他们轮流操作(Alice先手),每次操作时从下面的规则中任选一个: ·从某堆石子中取走一个 ·合并任意 ...
- #差分约束,SPFA#洛谷 1993 小 K 的农场
题目 分析 对于描述1,也就是\((a,b,-c)\),\(b\)比\(a\)至多多\(-c\) 对于描述2,也就是\((b,a,c)\),\(a\)比\(b\)至多多\(c\) 对于描述3,也就是\ ...