C#从入门到精通(21)—Mutex互斥锁在多线程、多进程下的使用

news2024/9/20 13:17:26

在这里插入图片描述

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家!人工智能学习网站

前言:

大家好,我是上位机马工,硕士毕业4年年入40万,目前在一家自动化公司担任软件经理,从事C#上位机软件开发8年以上!我们在开发上位机软件的过程中,有的时候需要实现同一个进程下的不同线程访问同一个资源的时候不要产生冲突,一个线程访问完了,另一个线程接着访问,或者是不同进程访问同一个资源的时候不要产生冲突,这时候就可以使用Mutex这个互斥锁来实现,Mutex这个类有几个构造函数,常用的分别介绍如下:

1、Mutex()

没有参数的构造函数,可以去实现线程同步。首先new一个Mutex 类的对象,然后在访问同一个资源之前调用WaitOne方法,代表调用WaitOne方法的线程此时独占这个资源,这时候别的线程只能等待这个互斥锁释放了以后才能访问,当我们执行完了我们想要执行的程序以后,再次调用ReleaseMutex方法去释放互斥锁,这时候别的线程就可以接着访问资源了。

 public partial class Form1 : Form
    {
        private static Mutex mut = new Mutex();
        public Form1()
        {
            InitializeComponent();

            for (int i = 0; i < 3; i++)
            {
                Thread myThread = new Thread(new ThreadStart(UseResource));
                myThread.Name = String.Format("Thread{0}", i + 1);
                myThread.IsBackground = true;
                myThread.Start();
            }
        }

        /// <summary>
        /// WaitOne到ReleaseMutex之间只能有一个线程进入
        /// </summary>
        private static void UseResource()
        {
            // 等待一直到可以安全进入,随后当前线程拥有互斥锁
            mut.WaitOne();

            Console.WriteLine("{0} has entered the protected area",
                Thread.CurrentThread.Name);

            // 模拟工作
            Thread.Sleep(500);

            Console.WriteLine("{0} is leaving the protected area\r\n",
                Thread.CurrentThread.Name);

            // 释放互斥锁
            mut.ReleaseMutex();
        }
    }

输出:

Thread1 has entered the protected area
Thread1 is leaving the protected area

Thread3 has entered the protected area
线程 0x85ec 已退出,返回值为 0 (0x0)。
Thread3 is leaving the protected area

Thread2 has entered the protected area
线程 0xec0 已退出,返回值为 0 (0x0)。
Thread2 is leaving the protected area

2、Mutex(Boolean)

这个构造函数传入一个bool类型变量,代表当前线程拥有了互斥锁,这时候就不需要调用WaitOne方法了,因为WaitOne方法也是相当于申请一个互斥锁。

  public partial class Form1 : Form
    {
        private static Mutex mut = new Mutex();
        public Form1()
        {
            InitializeComponent();

            // 创建一个互斥锁,当前调用线程拥有互斥锁
            mut = new Mutex(true);

            for (int i = 0; i < 3; i++)
            {
                Thread myThread = new Thread(new ThreadStart(UseResource));
                myThread.Name = String.Format("Thread{0}", i + 1);
                myThread.IsBackground = true;
                myThread.Start();
            }
            
            Console.WriteLine("当前调用线程拥有互斥体");
            Thread.Sleep(1000);

            Console.WriteLine("当前调用线程释放互斥体");
            mut.ReleaseMutex();
        }

        /// <summary>
        /// WaitOne到ReleaseMutex之间只能有一个线程进入
        /// </summary>
        private static void UseResource()
        {
            // 等待一直到可以安全进入,随后当前线程拥有互斥锁
            mut.WaitOne();

            Console.WriteLine("{0} has entered the protected area",
                Thread.CurrentThread.Name);

            // 模拟工作
            Thread.Sleep(500);

            Console.WriteLine("{0} is leaving the protected area\r\n",
                Thread.CurrentThread.Name);

            // 释放互斥锁
            mut.ReleaseMutex();
        }
    }

输出:

当前调用线程拥有互斥体
当前调用线程释放互斥体
Thread3 has entered the protected area
Thread3 is leaving the protected area

Thread1 has entered the protected area
线程 0x8cc8 已退出,返回值为 0 (0x0)。
Thread1 is leaving the protected area

Thread2 has entered the protected area
线程 0x57f4 已退出,返回值为 0 (0x0)。
Thread2 is leaving the protected area

3、Mutex(Boolean, String)

这个构造函数拥有两个参数,第一个参数指示调用的当前线程是否拥有互斥锁,第二个参数将这个互斥锁起了一个名字,这样,我们就可以在不同进程之间使用互斥锁,而不仅仅是同一个进程的不同线程下使用了。下面的程序第一次运行以后会弹出一个窗体,提示“关闭弹窗即可释放互斥体”;然后我们再次运行这个程序,两个程序就相当于两个进程了,因为第一个进程的互斥锁没有释放,所以第二次运行程序的时候不会弹出窗体,因为第二次运行的程序会卡在调用WaitOne那里等待第一个程序释放“MyMutex”这个互斥锁,然后当我们关闭第一个程序的弹窗以后,此时由于互斥锁被释放,所以第二个程序的弹窗会弹出来。

  public partial class Form1 : Form
    {
        private static Mutex mut = new Mutex();
        public Form1()
        {
            InitializeComponent();

            //与其他进程共享互斥体时,为互斥体起一个名称,比如MyMutex
            Mutex m = new Mutex(false, "MyMutex");

            Console.WriteLine("等待获取互斥体,如果被一个进程占用,则必须等它释放");
            m.WaitOne();

            Console.WriteLine("本进程拥有互斥体");
            MessageBox.Show("关闭弹窗即可释放互斥体");
            m.ReleaseMutex();
        }
    }

4、Mutex(Boolean, String, Boolean)

这个构造函数有三个参数,第一个参数指示调用的当前线程是否拥有互斥锁,第二个参数将这个互斥锁起了一个名字,第三个参数指示当前互斥锁是否已经被成功创建。下面的程序第一次运行以后弹出一个窗体“关闭弹窗即可释放互斥体”,因为第一次的进程成功拥有了这个互斥锁;第二次运行这个程序因为第一次的进程已经拥有互斥锁,并且没有被释放,所以mutexWasCreated会返回false,这样第二个进程就会卡在调用WaitOne那里。

  public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

           
            bool mutexWasCreated;//互斥锁是否被成功创建
            Mutex m = new Mutex(true,"MyMutex",out mutexWasCreated);

         
            if (!mutexWasCreated)//如果互斥锁已经存在,则等待拥有
            {
                Console.WriteLine("Waiting for the named mutex.");
                m.WaitOne();
            }

            MessageBox.Show("关闭弹窗即可释放互斥体");
            m.ReleaseMutex();
        }
    }

在这里插入图片描述

典型应用:

我们用下面的程序可以控制我们的winform程序只能被打开一次,这样就能防止软件被多次打开,在上位机软件开发中经常使用这个技术!

 static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            bool createNew;
            Mutex mt = new Mutex(true, "myMutex", out createNew);
            if (createNew)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
            else
            {
                MessageBox.Show("程序已经打开!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                Process.GetCurrentProcess().Kill();
            }
        }
    }

作者介绍

马工2017年硕士毕业,一直从事上位机软件开发工作,在我工作的第四年年薪突破了40万+,为了帮助跟我一样从底层出身的上位机软件工程师早日达到高级工程师的水平,早日找到30万+的工作,我根据多年项目经验,总结出了一系列可直接用于项目的C#上位机实战教程推荐给大家,目前在CSDN已经超过一千人订阅,如果你不甘贫庸,想像我一样早日拿到高薪,马工强烈推荐你早日学这套教程,雷军曾说这个世界上有99%的问题别人都遇到过,你要做的不是闷头干!而是找这个领域的专家问一下,这是最快速提升自己的方法!

年入30万+C#上位机实战必备教程推荐(点击下方链接即可访问文章)

1、《C#串口通信从入门到精通》
2、《C#与PLC通信从入门到精通 》
3、《C# Modbus通信从入门到精通》
4、《C#Socket通信从入门到精通 》
5、《C# MES通信从入门到精通》
6、《winform控件从入门到精通》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2096622.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言调用子函数时入/出栈(保护/恢复现场)全过程分析:以Cortex-M3为例

0 参考资料&工具 Cortex M3权威指南(中文).pdf keil5&#xff08;用于仿真查看寄存器、栈变化&#xff09;1 C语言调用子函数时出入/出栈&#xff08;保护/恢复现场&#xff09;全过程分析 使用C语言调用子函数是如何保护/恢复现场的呢&#xff1f;本文以Cortex-M3为例&a…

Zynq之IIC使用示例

前言 明确设计思路&#xff0c;精准定位问题&#xff0c;对于我们后期理解迭代工程有很大的帮助。 这就是我们常说的40%设计&#xff0c;20%编写和剩下的40%时间进行调试优化。 今天为大家带来的是Zynq-PS端的IIC使用demo&#xff0c;通过驱动外设DS1337来强化对IIC的使用方…

【C++二分查找 贪心】1552. 两球之间的磁力

本文涉及的基础知识点 C二分查找 贪心&#xff1a;决策兼容性 LeetCode1552. 两球之间的磁力 在代号为 C-137 的地球上&#xff0c;Rick 发现如果他将两个球放在他新发明的篮子里&#xff0c;它们之间会形成特殊形式的磁力。Rick 有 n 个空的篮子&#xff0c;第 i 个篮子的位…

百日草花语探秘:天长地久的情感寄托与丰富内涵解析

百日草宛如一颗璀璨的明珠&#xff0c;散发着独特的魅力。它那鲜艳夺目的花朵&#xff0c;仿佛是大自然用最细腻的笔触勾勒而成&#xff0c;每一朵都蕴含着无尽的奥秘与情感。当我们漫步于花海之间&#xff0c;不经意间与百日草相遇&#xff0c;那绚烂的色彩和别致的形态定会让…

李沐动手学深度学习:树叶分类竞赛

视频地址&#xff1a;30 第二部分完结竞赛&#xff1a;图片分类【动手学深度学习v2】 竞赛地址&#xff1a;https://www.kaggle.com/competitions/classify-leaves !nvidia-smi # 查看 GPU 信息 # !lscpu # 查看 CPU 信息 # !free -h # 查看内存(RAM) 信息 # !p…

datax编译:解决datax不支持MongoDB 6.0.10的问题

1. 需求及问题 最近使用datax同步MongoDB中的数据到hive,使用了mongodbreader和hdfswriter插件。MongoDB的版本是6.0.10,而datax的默认编译安装包中mongodbreader插件不支持MongoDB 6.0.10。 DataX工具介绍数据同步工具之DataX-CSDN博客 官方地址 https://github.com/alib…

模型 U型思考法(深度思考)

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。探索本质&#xff0c;创新求解。 1 U型思考法的应用 1.1 小罐茶的品牌创新 背景&#xff1a; 小罐茶作为一家新兴的茶叶品牌&#xff0c;面临着传统茶叶市场的激烈竞争和消费者需求的多样化。为了在…

地震模板代码 - 第三部分

Seismic stencil codes - part 3 — ROCm Blogs (amd.com) 2024年8月12日&#xff0c;作者&#xff1a;Justin Chang 和 Ossian O’Reilly。 在前两篇博客文章中&#xff0c;我们开发了一个 HIP 内核&#xff0c;能够计算地震波传播中常用的高阶有限差分。经过优化后&#xf…

Redis KEY操作实战手册:从设计到维护的全面指南

​ &#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索Redis的key的相关操作之旅✨ &#x1f44b; 大家好&#xff01;文本…

在 Ubuntu 环境下使用 VSCode 和 PlatformIO 下载程序到 Arduino Uno

安装 VSCode 访问 VSCode 官网 下载 .deb 包使用以下命令安装&#xff1a;sudo dpkg -i <下载的文件名>.deb sudo apt-get install -f安装 PlatformIO 扩展 在 VSCode 中&#xff0c;转到扩展市场&#xff08;CtrlShiftX&#xff09;搜索 “PlatformIO IDE”点击 “安装”…

刷题记录-HOT 100(一)40道

记录题解和思路。 一、哈希表解决问题 1、两数之和 思路&#xff1a; 创建哈希表&#xff1a; 初始化了一个空字典来存储已经访问过的数字及其对应的索引。 遍历数组&#xff1a; 逐一遍历数组中的每个元素。在遍历过程中&#xff0c;针对每个元素 num&#xff0c;计算出它…

手机FM LNA方案设计

一 概述 关于手机FM的使用&#xff0c;较为传统的则是在打开FM应用前先插入有线耳机才能使用FM应用。然而随着智能手机的进步以及有线耳机日益被无线蓝牙耳机所代替&#xff0c;内置FM LNA方案被应用的越来越多&#xff0c;无需插入有线耳机&#xff0c;复用例如GSM天线也能实…

跨语言障碍:全球语言翻译神器崛起

1.背景 工作中经常要查看纯英文文档和纯英文视频&#xff0c;尽管本人经历了1年多的英语培训&#xff0c;看英文资料依然非常吃力。 大模型出来后&#xff0c;KIMI能够帮助翻译纯英文的文档内容&#xff0c;但视频翻译还没有一个很好的工具。最近发现了一款通过大模型翻译文档…

yolov9目标检测pyside6可视化检测界面python源码-用于计数统计-摄像头可用

项目概述 此项目旨在利用YOLOv9&#xff08;You Only Look Once version 9&#xff09;这一先进的目标检测模型&#xff0c;实现实时视频流中的物体识别与计数。通过集成PySide6库&#xff0c;我们能够构建一个直观且易于使用的图形用户界面&#xff08;GUI&#xff09;&#…

基于SpringBoot+Vue+MySQL的社区维修平台

系统背景 系统管理也都将通过计算机进行整体智能化操作&#xff0c;对于社区维修平台所牵扯的管理及数据保存都是非常多的&#xff0c;例如住户管理、社区公告管理、维修工管理、维修订单管理、接单信息管理、订单信息管理、在线沟通管理、举报信息管理、留言板管理、系统管理等…

VR虚拟驾驶未来发展_vr自动驾驶汽车所带来的改变

在自动驾驶汽车的基础上&#xff0c;VR虚拟现实技术的应用也让自动驾驶汽车更加智能化&#xff0c;能够实现更高级的驾驶体验&#xff0c;今天这篇文章就和大家一起探讨一下 VR虚拟驾驶未来发展的趋势&#xff0c;以及虚拟现实自动驾驶汽车所带来的几个改变。 一、VR 虚拟驾驶未…

WebAssembly技术实践

文章目录 知识学习优点 开启本地临时服务器方式一、命令安装方式二、直接在vscode的插件 测试程序异常处理 最近在看WebAssembly相关的知识&#xff0c;在本地运行&#xff0c;记录下来&#xff0c;方便备查。 知识学习 WebAssembly是一种高性能二进制格式、用于在各种现代硬件…

C++基础面试题 | C++中static的作用?什么场景下会使用static?

回答重点&#xff1a;修饰局部变量 修饰全局变量或函数 修饰类的成员变量或函数 修饰局部变量&#xff1a;当static用于修饰局部变量时&#xff0c;该变量的存储位置在程序执行期间保持不变&#xff0c;并且只在程序执行到该变量的声明处时初始化一次。即使函数被多次调用&…

【Python报错已解决】“ModuleNotFoundError: No module named ‘packaging‘“

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引言&#xff1a;一、问题描述1.1 报错示例&#xff1a;尝试导入不存在的模块时&#xff0c;可能会看到以下错误信息。…

详解CSS

目录 CSS 语法 引入方式 选择器 标签选择器 类选择器 ID选择器 通配符选择器 复合选择器 常用CSS color font-size border width和height padding 外边距 CSS CSS(Cascading Style Sheet)&#xff0c;层叠样式表, ⽤于控制⻚⾯的样式. CSS 能够对⽹⻚中元素位置…