在C#中使用互斥量解决多线程访问共享资源的冲突问题
在阿里云上对互斥量的概述:互斥量的获取是完全互斥的,即同一时刻,互斥量只能被一个任务获取。而信号量按照起始的计数值的配置,可以存在多个任务获取同一信号量的情况,直到计数值减为0,则后续任务无法再获取信号量,当信号量的计数初值设置为1,同样有互斥的效果。但信号量无法避免优先级反转问题。
注意事项:
⑴ 互斥量只能由获取该互斥量的任务的释放,不能由其他任务释放。
⑵ 互斥量已被当前任务获取,若当前任务再次获取互斥量则返回错误。
微软官方文档的解释因为加了很多的名词,看起来解释得深入,实际上有点绕。但是看代码就好理解一些。
前面的文章《在C#中使用信号量解决多线程访问共享资源的冲突问题》,可能看过的就明白为什么使用信号量,就是限制同步数,任何时刻只有一个线程对资源的操作,这样肯定不会发生冲突,但是这样会限制了性能。
信号量就是限制同步线程的数量,解决多线程对共享资源可能产生的冲突问题,可能还是使用锁、原子操作或者互斥量比较正规一些。
1、互斥量的简单使用
问题:两个任务同时执行,每个任务都产生1到10的随机数,最后统计所产生的1到10的数字个数。
实现代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics.Metrics;namespace MultiThread20230224
{public partial class Form2 : Form{public static int[] PSPArr = new int[11];public int ExecCount = 0;public static Mutex mutex = new Mutex(); // 创建互斥量public Form2(){InitializeComponent();Control.CheckForIllegalCrossThreadCalls = false;}private void button1_Click(object sender, EventArgs e){for(int i=0; i<PSPArr.Length;i++){PSPArr[i] = 0;}ExecCount = int.Parse(textBox4.Text);if( ExecCount == 0 || ExecCount==null) {ExecCount= 10;}DateTime start = DateTime.Now;SubTask ST1 = new SubTask(1);SubTask ST2 = new SubTask(2);Thread t1 = new Thread(ST1.DoTask);Thread t2 = new Thread(ST2.DoTask);t1.Start(ExecCount);t2.Start(ExecCount);t1.Join();t2.Join();DateTime end = DateTime.Now;TimeSpan tspan = end - start;string time =((int)tspan.TotalMilliseconds).ToString();textBox1.Text = "";textBox2.Text = "";textBox3.Text = "";//显示统计结果for (int i=1;i<11;i++){string S1 = "×";textBox1.Text += i.ToString() + " ==> " + ST1.Arr[i] + Environment.NewLine;textBox2.Text += i.ToString() + " ==> " + ST2.Arr[i] + Environment.NewLine;if (PSPArr[i]== ST1.Arr[i]+ ST2.Arr[i]){S1 = "√";}textBox3.Text += i.ToString() + " ==> " + PSPArr[i] +" "+S1+ Environment.NewLine;}label6.Text= time.ToString();}}public class SubTask{string TaskName = "";public int[] Arr=new int[11];public SubTask(int TaskNum) { TaskName = "任务"+TaskNum.ToString();}public void DoTask(object obj){int ii = (int)obj;for (int i = 0; i < ii; i++){int num = new Random().Next(1, 11);Arr[num] += 1;//本地计数// 加锁,防止多个线程同时修改counts数组Form2.mutex.WaitOne();Form2.PSPArr[num] +=1;Form2.mutex.ReleaseMutex();}}}}
显示结果:

2、信号量与互斥量的结合使用
与上面的问题相似,启动100个任务,每个任务产生一个1到10的随机数,最后统计所产生的1到10的数字个数。
实现代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace MultiThread20230224
{public partial class Form3 : Form{static SemaphoreSlim sem = new SemaphoreSlim(3);static Mutex mutex = new Mutex();static int[] Arr = new int[11];static Random random = new Random();List<Thread> threads = new List<Thread>();public Form3(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){for (int i = 1; i < 11; i++){Arr[i]=0;}textBox1.Text= "";DateTime start = DateTime.Now;threads.Clear();for (int i = 0; i < 100; i++){Thread t = new Thread(new ThreadStart(Task));threads.Add(t);}foreach (Thread t in threads){t.Start();}foreach (Thread t in threads){t.Join();}DateTime end = DateTime.Now;TimeSpan tspan = end - start;string time = ((int)tspan.TotalMilliseconds).ToString();//显示统计结果int ITemp = 0;for (int i = 1; i < 11; i++){ITemp += Arr[i];textBox1.Text += i.ToString() + " ==> " + Arr[i] + Environment.NewLine;}textBox1.Text += " 总数 ==> " + ITemp.ToString() + Environment.NewLine;textBox1.Text += "耗时 ==> " + time.ToString()+" 毫秒";}static void Task(){sem.Wait();int num = random.Next(1, 11);mutex.WaitOne();Arr[num]++;mutex.ReleaseMutex();sem.Release();}}
}
显示结果:

上面的程序信号量用于限制线程的同步数,互斥量用于限制同时访问共享资源,保证不发生冲突。
如果为了测试信号量的大小以及生成随机数的个数大小对程序执行时间的影响,可是改变sem的大小,同时改变Task方法。
改变sem:
int semaphoreCount = Convert.ToInt32(textBox3.Text);sem = new SemaphoreSlim(semaphoreCount);
改变Task方法:
static void Task(object count){sem.Wait();int num = random.Next(1, 11);mutex.WaitOne();Arr[num]++;mutex.ReleaseMutex();sem.Release((int)count); // 释放指定数量的信号量}
改变线程的启动:
foreach (Thread t in threads){t.Start(10); //将产生随机数的个数作为参数传入}
信号量的个数大小对程序的执行快慢有一定影响。一方面,如果信号量的个数较小,可能会导致线程需要等待的时间较长,从而降低程序的执行速度。另一方面,如果信号量的个数过多,会导致操作系统需要维护的信号量数量过多,也会增加程序的开销和系统负担。一般来说,合理设置信号量的个数可以提高程序的执行效率。根据实际需求,可以进行性能测试,不断调整信号量的个数,以达到最优的执行效果。
信号量的作用是控制同一时间可执行的线程数量。
互斥量的作用是确保同一时间只有一个线程访问共享资源。
相关文章:
⑴ C#线程的参数传递、获取线程返回值以及处理多线程冲突
⑵ 在C#中使用信号量解决多线程访问共享资源的冲突问题
相关文章:
在C#中使用互斥量解决多线程访问共享资源的冲突问题
在阿里云上对互斥量的概述:互斥量的获取是完全互斥的,即同一时刻,互斥量只能被一个任务获取。而信号量按照起始的计数值的配置,可以存在多个任务获取同一信号量的情况,直到计数值减为0,则后续任务无法再获取…...
JavaEE进阶第六课:SpringBoot配置文件
上篇文章介绍了SpringBoot的创建和使用,这篇文章我们将会介绍SpringBoot配置文件 目录1.配置文件的作用2.配置文件的格式2.1 .properties语法2.1.1.properties的缺点2.2 .yml语法2.2.1优点分析2.2.2配置与读取对象2.2.3配置与读取集合2.2.4补充说明3.设置不同环境的…...
MySQL基础(一)SQL分类、导入、SELECT语句,运算符
目录 MySQL安装以及相关工具 SQL分类 导入数据 最基本的SELECT语句 SELECT FROM 列的别名 去除重复行 着重号 查询常数 描述表结构 过滤数据(重要) 运算符 算数运算符 比较运算符 符号运算符 非符号运算符 逻辑运算符 位运算符 MySQL安…...
反激与正激的区别
之前学习了正激开关电源,但是对于正激和反激一直不是很清楚,网上找了一篇,觉得感觉该可以,以此记录。正激和反激是两种不同的开关电源技术一、正激(1)概述正激式开关电源是指使用正激高频变压器隔离耦合能量…...
王道操作系统课代表 - 考研计算机 第四章 文件管理 究极精华总结笔记
本篇博客是考研期间学习王道课程 传送门 的笔记,以及一整年里对 操作系统 知识点的理解的总结。希望对新一届的计算机考研人提供帮助!!! 关于对 “文件管理” 章节知识点总结的十分全面,涵括了《操作系统》课程里的全部…...
前端开发规范,你真的了解吗?一起来学习一下前端开发规范,让你的代码高级起来!
代码规范 1 编码风格规范 1.1 使用ES6风格编码源码 定义变量使用let ,定义常量使用const 使用export ,import 模块化 1.2 组件 props 原子化 提供默认值 使用 type 属性校验类型 使用 props 之前先检查该 prop 是否存在 1.3 避免 this.$parent 1.4 谨慎使用 …...
Licode—基于webrtc的SFU/MCU实现
1. webrtc浅析webrtc的前世今生、编译方法、行业应用、最佳实践等技术与产业类的文章在网上卷帙浩繁,重复的内容我不再赘述。对我来讲,webrtc的概念可以有三个角度去解释:(1).一个W3C和IETF制定的标准,约定…...
开发运维工具推荐 --- 解决远程访问局域网服务的问题。开发调试推荐
一、FastNat 可为您解决的问题1. 没公网服务器,需要发布本地的站点或网络程序到公网上,供他人访问;此项功能大大方面开发人员进行远程调试,微信小程序等开发工作进行。2. 需要远程到在其他网络中的设备,但两处的网络不…...
【华为OD机试 】单词倒序(C++ Java JS Python)
文章目录 题目描述输入描述输出描述备注用例题目解析C++ 解法JavaScript算法源码Java算法源码Python解法题目描述 输入单行英文句子,里面包含英文字母,空格以及,.?三种标点符号,请将句子内每个单词进行倒序,并输出倒序后的语句。 输入描述 输入字符串S,S的长度 1 ≤ N…...
PLC 诊断故障的基本原理
(1)东欢坨选煤厂机电设备故障信号主要取自开关量信号,PLC 通过开关量的通和断对设备进行故障诊断。PLC 对开关量的识别是通过输入模块来实现的。PLC 控制设备运行时,设备中的温度、压力、急停、跑偏、速度、过热以及各种按钮和行程开关的传感器与 PLC 输入模块相连接,输入模块的…...
QT打开外部程序并嵌入Qt子窗口的缺点
首先可以参考如下文章: QT打开外部程序并嵌入Qt界面_qt界面嵌入外部应用程序_初学小白Lu的博客-CSDN博客 Qt嵌入外部程序界面初探_qt嵌入其他程序窗口_liming4675的博客-CSDN博客 QT 如何把外部程序嵌入到QT界面_qt嵌入其他程序窗口_hellokandy的博客-CSDN博客 Qt界…...
如何系统地学习 C++ 语言?
C作为具有广泛适用性的编程语言,学习C的人越来越多,但是如何系统地学习C还是个问题,下面我们一起来看一下C学习的方法有哪些吧。 首先,要学习C,最重要的就是掌握C的基础知识。 比如数据结构、算法、微积分等。这些都是…...
【数据结构】单链表
链表1.为什么存在链表2.链表的概念3.单链表的实现4.测试1.为什么存在链表 我们在学习顺序表的时候,了解到顺序表有一定的缺陷:(1)在中间插入数据和删除数据需要挪动数据,时间复杂度是O(N)&…...
Windows 右键菜单扩展容器 [开源]
今天给大家分享一个我做的小工具,可以自定义扩展右键菜单的功能来提高工作效率,效果图如下: 如上图,右键菜单多了几个我自定义的菜单: 复制文件路径 复制文件夹路径 我的工具箱 <走配置文件动态创建子菜单&#x…...
爆文制造机!小红书热榜3个方向,告诉你选题诀窍!
我们知道,不论是达人创作内容,还是品牌制定Brief,都需要提前调研筛选海量信息,这时候如果有一个自己的内容素材库,就省事多啦。按照内容需求,我们可以按3个角度划分小红书内容素材:笔记类型、竞…...
【Web安全社工篇】——水坑攻击
作者名:白昼安全主页面链接: 主页传送门创作初心: 以后赚大钱座右铭: 不要让时代的悲哀成为你的悲哀专研方向: web安全,后渗透技术每日鸡汤:努力赚钱不是因为爱钱“水坑攻击”,黑客攻…...
SpringBoot 整合 MongoDB 实现数据的增删改查!
一、介绍在 MongoDB 中有三个比较重要的名词:数据库、集合、文档!数据库(Database):和关系型数据库一样,每个数据库中有自己的用户权限,不同的项目组可以使用不同的数据库集合(Colle…...
VUE前端常问面试题
文章目录一、VUE前端常问面试题二、文档下载地址一、VUE前端常问面试题 1、MVC和MVVM 区别 MVC:MVC全名是 Model View Controller,即模型-视图-控制器的缩写,一种软件设计典范。 Model(模型):是用于处理应用程序数据逻辑部分。通…...
c++中map/unordered_map的不同遍历方式以及结构化绑定
文章目录方式一:值传递遍历方式二:引用传递遍历方式三:使用迭代器遍历方式四:结构化绑定(c17特性)结构化绑定示例(1)元组tuple结构化绑定(2)结构体结构化绑定(3ÿ…...
Kafka系列之:Kraft模式
Kafka系列之:Kraft模式 一、Kraft架构二、Kafka的Kraft集群部署三、初始化集群数据目录四、创建KafkaTopic五、查看Kafka Topic六、创建生产者七、创建消费者一、Kraft架构 Kafka元数据存储在zookeeper中,运行时动态选举controller,由controller进行Kafka集群管理。Kraft模式…...
环境配置与基础教程:保姆级教程:在 Mac M 芯片上利用 MPS 加速 YOLO 训练与推理的完整环境搭建
写在前面:为什么你的 Mac 也能跑深度学习? 几年前,如果有人告诉你用 MacBook 训练深度学习模型,你大概会笑出声。那时候 Mac 上的 PyTorch 只能依赖 CPU 吭哧吭哧地算,训练一个小模型都要等到天荒地老。但自从 Apple Silicon 芯片(M1、M2、M3、M4,以及最新的 M5)横空出…...
C#调用打印机老是失败?先别怪代码,这5个Windows驱动设置坑你踩过几个?
C#调用打印机故障排查指南:5个被忽视的Windows驱动陷阱 当你信心满满地写完C#打印代码,点击"打印"按钮后却只收获了一片寂静——打印机毫无反应,控制台也没有任何错误提示。这种挫败感每个C#开发者都经历过。但先别急着重写代码&am…...
从零到一:RK3588s平台imx415双目相机模组点亮与ISP调优实战
1. 环境准备:从零搭建开发环境 第一次接触RK3588s平台时,最头疼的就是环境搭建。我用的Firefly AIO-3588S-JD4开发板配套资料比较分散,光是找齐所有软件包就花了半天时间。这里分享下我的踩坑经验: 硬件清单必须严格核对&#x…...
stm32开发者如何快速接入大模型api实现智能对话功能
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 STM32开发者如何快速接入大模型API实现智能对话功能 为嵌入式设备增加自然语言交互能力,是许多STM32开发者希望实现的功…...
BilibiliDown终极指南:快速下载B站视频的免费高效方案
BilibiliDown终极指南:快速下载B站视频的免费高效方案 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/b…...
如何免费解锁英雄联盟历史回放?ROFL-Player终极解决方案
如何免费解锁英雄联盟历史回放?ROFL-Player终极解决方案 【免费下载链接】ROFL-Player (No longer supported) One stop shop utility for viewing League of Legends replays! 项目地址: https://gitcode.com/gh_mirrors/ro/ROFL-Player 你是否曾因为英雄联…...
手把手教你用Python通过RS-232控制ITECH IT63XX电源(附完整代码)
用Python自动化控制ITECH可编程电源的工程实践指南 在硬件开发和自动化测试领域,精确控制直流电源是确保产品质量的关键环节。ITECH IT63XX系列可编程电源以其稳定性和丰富的接口选项,成为工程师实验室的常见设备。本文将带您从零开始构建一个完整的Pyth…...
2026年5月权威实测:Claude Code必装的7个MCP,效率翻倍
Top 1:GitHub MCP —— “衔枚之钉” 如果说MCP服务器里只能留下一个,那GitHub MCP绝对是不可动摇的“钉子户”。它不仅是每个开发者工作流的起点,更是将AI代理从“代码提示者”推向“自主开发者”的核心动力。 它的核心价值是**“端到端的工…...
3分钟掌握Ofd2Pdf:轻松解决OFD转PDF的格式兼容难题
3分钟掌握Ofd2Pdf:轻松解决OFD转PDF的格式兼容难题 【免费下载链接】Ofd2Pdf Convert OFD files to PDF files. 项目地址: https://gitcode.com/gh_mirrors/ofd/Ofd2Pdf Ofd2Pdf是一款专为中文用户设计的开源工具,能够高效地将OFD格式文件转换为通…...
Prompt-Builder:开源提示词工程框架,让AI交互从玄学变科学
1. 项目概述:一个为AI时代量身定制的提示词工程利器如果你和我一样,深度使用过ChatGPT、Claude、Midjourney这类大模型,那你一定有过这样的体验:面对一个复杂任务,你精心构思的提问,换来的却是一个平庸甚至…...
