聊透多线程编程-线程互斥与同步-9.C# 线程互斥实现方式

目录

1. 锁机制 (Locking Mechanisms)

(1) lock 关键字

(2) Monitor 类

2. 跨进程互斥机制

3. 信号量机制

(1) Semaphore 和 SemaphoreSlim

4. 读写锁机制

(1) ReaderWriterLockSlim

5. 原子操作机制

(1) Interlocked 类

6. 自旋锁机制

(1) SpinLock


线程互斥是一种保证在同一时刻只有一个线程能够访问共享资源的机制。它是一种排他性的访问控制,目的是防止多个线程同时对共享资源进行读写操作而导致的数据不一致或其他错误。比如多个线程同时对一个银行账户进行取款操作,如果不进行互斥控制,就可能出现账户余额错误的情况。

在 .NET 中,线程互斥(Mutual Exclusion)有多种实现方式,以下是 .NET 中常见的线程互斥实现方式:

实现方式

特点

使用场景

lock关键字

简单易用,自动管理锁

进程内同步

Monitor类

更细粒度控制锁

显式控制锁的场景

Mutex类

支持跨进程

多进程间同步

信号量Semaphore 

限制最大并发数

控制资源访问数量

读写锁

ReaderWriterLockSlim

允许多线程同时读,但只允许一个线程写

读多写少的场景

Interlocked类

原子操作,高效

简单数值操作

自旋锁SpinLock

自旋等待锁,避免上下文切换

短时间临界区

根据具体需求选择合适的线程互斥机制,能够有效提升程序的性能和可靠性。


1. 锁机制 (Locking Mechanisms)

(1) lock 关键字

  • 原理: lock 是 C# 中的一个语法糖,它实际上是调用了 Monitor.Enter 和 Monitor.Exit 方法来实现的。当一个线程执行到 lock 语句块时,它会尝试获取锁对象上的排他锁。如果成功获取,则进入临界区执行代码;否则,该线程将被阻塞直到锁可用。
  • 特点:
    • 简单易用,适用于单一应用程序域内的线程同步。
    • 自动处理异常情况下的锁释放。
  • 示例:
private readonly object _lockObject = new object();public void CriticalSection()
{lock (_lockObject){// 访问共享资源的代码}
}

(2) Monitor 类

  • 原理: Monitor 提供了比 lock 更灵活的同步机制,允许手动控制进入和退出临界区。通过调用 Monitor.Enter 获取锁,Monitor.Exit 释放锁。此外,还支持条件变量(Wait, Pulse, PulseAll)以实现更复杂的同步逻辑。
  • 特点:
    • 支持超时等待获取锁的能力。
    • 可以与条件变量一起使用,支持复杂的同步模式。
  • 示例:
private readonly object _lockObject = new object();public void CriticalSection()
{try{Monitor.Enter(_lockObject);// 访问共享资源的代码}finally{Monitor.Exit(_lockObject);}
}


2. 跨进程互斥机制

(1) Mutex 类

  • 原理: Mutex 是一种内核级别的同步对象,可以用于跨进程的线程同步。当一个线程获取了 Mutex 对象的所有权时,其他线程会被阻塞,直到该线程释放 Mutex。
  • 特点:
    • 支持跨进程同步。
    • 性能较 lock 和 Monitor 稍低,因为它是内核对象。
  • 示例:
using System.Threading;private static Mutex _mutex = new Mutex();public void CriticalSection()
{_mutex.WaitOne(); // 获取锁try{// 访问共享资源的代码}finally{_mutex.ReleaseMutex(); // 释放锁}
}


3. 信号量机制

(1) Semaphore 和 SemaphoreSlim

  • 原理: 信号量是一种允许多个线程同时访问共享资源的同步机制,但限制最大并发数。Semaphore 支持跨进程,而 SemaphoreSlim 是轻量级版本,仅限于当前进程内使用。
  • 特点:
    • Semaphore 支持跨进程同步。
    • SemaphoreSlim 性能更高,适合单进程场景。

示例: (SemaphoreSlim)

using System.Threading;private static SemaphoreSlim _semaphore = new SemaphoreSlim(1); // 最大并发数为 1public async Task CriticalSectionAsync()
{await _semaphore.WaitAsync();try{// 访问共享资源的代码}finally{_semaphore.Release();}
}


4. 读写锁机制

(1) ReaderWriterLockSlim

  • 原理: ReaderWriterLockSlim 是一种优化的读写锁,允许多个线程同时读取共享资源,但只允许一个线程写入资源。通过 EnterReadLock、EnterWriteLock 和 EnterUpgradeableReadLock 方法分别管理读锁、写锁和可升级的读锁。
  • 特点:
    • 适合读多写少的场景。
    • 提高了读操作的并发性能。
  • 示例:
private static ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();public void ReadOperation()
{_rwLock.EnterReadLock();try{// 读取共享资源的代码}finally{_rwLock.ExitReadLock();}
}public void WriteOperation()
{_rwLock.EnterWriteLock();try{// 写入共享资源的代码}finally{_rwLock.ExitWriteLock();}
}


5. 原子操作机制

(1) Interlocked 类

  • 原理: Interlocked 提供了一些原子操作方法,用于对简单数据类型(如整数)进行线程安全的操作。这些操作在硬件级别上保证了原子性,无需显式加锁。
  • 特点:
    • 高效,无需显式加锁。
    • 适用于简单的数值操作。
  • 示例:
using System.Diagnostics.Metrics;private int _counter = 0;public void IncrementCounter()
{Interlocked.Increment(ref _counter);
}public void DecrementCounter()
{Interlocked.Decrement(ref _counter);
}


6. 自旋锁机制

(1) SpinLock

  • 原理: SpinLock 是一种自旋锁,线程会不断循环检查锁是否可用,而不是进入等待状态。这种方式避免了上下文切换开销,但在长时间锁定时会浪费 CPU 资源。
  • 特点:
    • 适合非常短的临界区。
    • 避免上下文切换的开销。
  • 示例:
using System.Threading;private SpinLock _spinLock = new SpinLock();public void CriticalSection()
{bool lockTaken = false;try{_spinLock.Enter(ref lockTaken);// 访问共享资源的代码}finally{if (lockTaken)_spinLock.Exit();}
}

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

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

相关文章

eNSP无法启动AR报错码40,而且按照eNSP帮助手册排查都没用,我的处理方法【自己存档版】

问题: 已经尝试过eNSP的帮助手册,发现都没用! eNSP启动AR设备报错码40且常规排查无效时,可尝试以下解决方案(按优先级排序): 1. 关闭Hyper-V和Windows沙盒(我是这个问题&#xff0…

秒杀系统解决两个核心问题的思路方法总结:1.库存超卖问题;2.用户重复抢购问题。

秒杀系统解决两个核心问题 秒杀系统解决两个核心问题:一、解决库存超卖的核心逻辑:解释:原子性保证: 二、如何避免重复抢购:使用 Redis 做唯一标识判断优点: 三、流程完整梳理:四、通过数据库建…

【集成电路版图设计学习笔记】3.基本电路元件(MOS,电容,电阻)

一、MOSFET 在版图设计中,要定义一个mosfet,最关键的层次是polysilicon(多晶硅)和active(有源区)。用有源区定义了一个矩形的区域,在这个区域内才可以形成一个有源器件,然后再用多晶…

蓝桥杯之差分题型

一维差分 问题描述 给定一个长度为 nn 的序列 aa。 再给定 mm 组操作,每次操作给定 33 个正整数 l,r,dl,r,d,表示对 al∼ral∼r​ 中的所有数增加 dd。 最终输出操作结束后的序列 aa。 Update:由于评测机过快,n,mn,m 于 2024…

深入剖析 C/S 与 B/S 架构及网络通信基础

目录 C/S 架构详解​ 概念与示例​ 优点​ B/S 架构详解​ 概念与示例​ 优势​ 缺点​ C/S 与 B/S 的区别​ 架构组成​ 使用场景​ 开发和维护​ 安全性​ 网络通信基础​ IP 地址​ MAC(物理地址)​ 端口​ 路由器​ 网关​ 子网掩…

常见免杀框架的使用(3款)---【AniYaGUI1.2.0、AV_Evasion_Tool掩日、FoxBypass_V1.0】

一、AniYaGUI1.2.0免杀框架 环境:虚拟机Win10 、云服务器 工具:Xshell、CobaltStrike 项目下载地址: https://github.com/piiperxyz/AniYa 1. 安装Go语言环境 确保Win10虚拟机安装 Golang 且环境变量中包含 go 否则⽆法编译(注…

Apache HTTPD 换行解析漏洞

漏洞介绍 CVE-2017-15715 Apache HTTPD 是一个广泛使用的 HTTP 服务器,可以通过 mod_php 模块来运行 PHP 网页。在其 2.4.0 到 2.4.29 版本中存在一个解析漏洞,当文件名以 1.php\x0A 结尾时,该文件会被按照 PHP 文件进行解析,这…

常用开发环境/工具版本选择(持续更新中)

操作系统:Ubuntu Server Version(LTS)Latest Sub VerRelease Time24.04(Noble Numbat)24.04.22025-02-1622.04(Jammy Jellyfish)22.04.52024-09-1120.04(Focal Fossa)20.04.62023-03-1418.04(Bionic Beaver)18.04.62021-09-1516.04.7(Xenial…

STM32 认识STM32

目录 什么是嵌入式? 认识STM32单片机 开发环境安装 安装开发环境 开发板资源介绍 单片机开发模式 创建工程的方式 烧录STM32程序 什么是嵌入式? 1.智能手环项目 主要功能有: 彩色触摸屏 显示时间 健康信息:心率&#…

C#核心笔记——(六)框架基础

我们在编程时所需的许多核心功能并不是由C#语言提供的,而是由.NET Framework中的类型提供的。本节我们将介绍Framework在基础编程任务(例如虚的等值比较、顺序比较以及类型转换)中的作用。我们还会介绍Framework中的基本类型,例如String、DateTime和Enum. 本章中的绝大部分…

AI——K近邻算法

文章目录 一、什么是K近邻算法二、KNN算法流程总结三、Scikit-learn工具1、安装2、导入3、简单使用 三、距离度量1、欧式距离2、曼哈顿距离3、切比雪夫距离4、闵可夫斯基距离5、K值的选择6、KD树 一、什么是K近邻算法 如果一个样本在特征空间中的k个最相似(即特征空…

transient关键字深度解析

Java transient 关键字深度解析 transient(意思:瞬时的,瞬间的) 1. 核心概念 (1) 基本定义 作用:标记字段不参与序列化 适用场景: 敏感数据(如密码、密钥) 临时计算字段 依赖运行时环境的字段(如Thread对象) (2) 语法示例 java public class User implements Se…

信刻电子档案蓝光光盘刻录安全检测长期归档

信刻一直致力于为档案馆、各行业档案部门,提供跨网数据交换、电子档案数据磁光异质备份归档解决方案。所研制的电子档案光盘智能长期归档系统,满足国产环境下”刻、管、存、检、用”全生命周期管理应用需求,能够提供一份离线归档、一份近线存…

Word 中“母版页”的等效机制

Word 和 PowerPoint 不太一样——**Word 实际上没有像 PowerPoint 那样的“母版页(Master Page)”**功能。但它有1个和“母版页”功能类似的东西,可能造成你看到的“校徽自动出现在每一页”的现象: ✅ Word 中“母版页”的等效机制…

Go:反射

为什么使用反射 在编程中,有时需编写函数统一处理多种值类型 ,这些类型可能无法共享同一接口、布局未知,甚至在设计函数时还不存在 。 func Sprint(x interface{}) string {type stringer interface {String() string}switch x : x.(type) …

SS25001-多路复用开关板

1 概述 1.1 简介 多路复用开关板是使用信号继电器实现2线制的多路复用开关板卡;多路复用开关是一种可以将一个输入连接到多个输出或一个输出连接到多个输入的拓扑结构。这种拓扑通常用于扫描,适合将一系列通道自动连接到公共线路的的设备。多路复用开…

vue3 nprogress 使用

nprogress 介绍与作用 1.nprogress 是一个轻量级的进度条组件,主要用于在页面加载或路由切换时显示一个进度条,提升用户体验。它的原理是通过在页面顶部创建一个 div,并使用 fixed 定位来实现进度条的效果 2.在 Vite Vue 3 项目中&#xf…

Jsp技术入门指南【六】jsp脚本原理及隐式对象

Jsp技术入门指南【六】jsp脚本原理及隐式对象 前言一、JSP 脚本元素1.1 声明1.2 表达式1.3 脚本标签 二、JSP 的隐式对象是什么三、隐式对象详解outrequestsessionapplicationconfigexception 前言 在之前的博客中,我们已经介绍了JSP的环境搭建、编译文件查找以及生…

vue3推荐的移动table库

vxe-table https://gitee.com/js-class/vxe-table#https://gitee.com/link?targethttps%3A%2F%2Fvxetable.cn 文档api https://vxetable.cn/#/component/table/other/bookkeepingVoucher 引入步骤 安装 npm install xe-utils vxe-tablenext 在项目main.js引入 import …

HOOPS Exchange 与HOOPS Communicator集成:打造工业3D可视化新标杆!

一、概述 在工业3D开发、BIM建筑、数字孪生和仿真分析等高端应用场景中,数据格式复杂、模型体量庞大、实时交互体验要求高,一直是困扰开发者的难题。Tech Soft 3D旗下的HOOPS Exchange和HOOPS Communicator,正是解决这类问题的黄金搭档。二者…