C# 信号量(Semaphore)详细使用案例

文章目录

    • 简介
    • 信号量的工作原理
    • 使用场景
    • 使用示例
    • 其他使用实例
      • 1. 数据库连接池管理
      • 2. 文件读写同步
      • 3. 生产者消费者问题
      • 4. 打印任务队列同步
      • 5. Web服务器并发请求限制

简介

在C#中,信号量(Semaphore)是.NET框架提供的一个同步类,位于System.Threading命名空间下,用于控制并发访问特定资源的线程数量。它是一种更灵活的线程同步机制,通过维护一个计数器来管理资源的可用性。

信号量的工作原理

初始化时,可以指定一个初始计数值,这个值表示可以同时访问共享资源的线程数。

  • 当线程调用WaitOne()方法时,如果信号量计数器大于0,则计数器减1,并允许线程继续执行;若计数器为0,则线程被阻塞并等待其他线程释放信号量。
  • 通过调用Release()方法,可以增加信号量的计数值,从而允许一个或多个等待中的线程获取信号量并继续执行。

使用场景

  1. 资源池管理:例如,限制数据库连接池中同时活动的连接数,以防止过多连接导致系统过载。
  2. 互斥锁(Mutex)替代:当信号量初始化为1时,它相当于一个互斥锁,确保同一时间只有一个线程能访问临界区。
  3. 多线程同步:对于可同时由多个线程使用的有限资源,如许可、通道容量等,可以通过设置适当的信号量计数值来协调多个线程的并发访问。

使用示例

using System.Threading;// 创建一个最多允许5个线程同时访问的信号量
Semaphore semaphore = new Semaphore(5, 5); // 第一个参数是初始信号量,第二个参数是最大信号量void AccessResource()
{// 尝试获取信号量semaphore.WaitOne();try{// 这里是临界区,只有拿到信号量的线程才能进入// 执行对共享资源的操作...}finally{// 资源操作完毕后,释放信号量semaphore.Release();}
}// 在多个线程中调用AccessResource()函数
// ...

在上述代码中,Semaphore(5, 5)创建了一个信号量,初始和最大并发访问数均为5。当超过5个线程尝试访问资源时,额外的线程将会阻塞直到有其他线程完成操作并释放信号量。每个成功获取信号量的线程在完成资源访问后都会调用Release()将信号量递增,以便后续线程继续访问。

其他使用实例

1. 数据库连接池管理

Semaphore connectionSemaphore = new Semaphore(10, 10); // 最多允许10个并发连接void ExecuteQuery()
{connectionSemaphore.WaitOne();try{var connection = GetDatabaseConnection(); // 获取数据库连接// 执行SQL查询...}finally{ReleaseDatabaseConnection(connection); // 释放数据库连接connectionSemaphore.Release();}
}// 多线程环境下,多个线程调用ExecuteQuery()函数执行数据库操作

2. 文件读写同步

Semaphore fileSemaphore = new Semaphore(1, 1); // 文件操作为互斥,同一时间仅允许一个线程访问void WriteToFile(string content)
{fileSemaphore.WaitOne();try{using (var writer = new StreamWriter("file.txt")){writer.WriteLine(content);}}finally{fileSemaphore.Release();}
}// 多线程环境下,同时写入文件但不会产生数据混乱

3. 生产者消费者问题

Semaphore bufferSemaphore = new Semaphore(10, 10); // 缓冲区大小为10void Producer()
{var item = CreateItem();bufferSemaphore.WaitOne();try{Buffer.Add(item); // 将产品放入缓冲区}finally{bufferSemaphore.Release();}
}void Consumer()
{bufferSemaphore.WaitOne();try{var item = Buffer.Take(); // 从缓冲区取出产品进行消费Consume(item);}finally{bufferSemaphore.Release();}
}// 生产者和消费者线程通过信号量控制对缓冲区的存取操作

4. 打印任务队列同步

Semaphore printerSemaphore = new Semaphore(1, 1); // 打印机为独占资源void PrintJob()
{printerSemaphore.WaitOne();try{SendToPrinter(JobQueue.Dequeue()); // 从打印任务队列中取出并发送打印任务}finally{printerSemaphore.Release();}
}// 多线程环境下,打印机按顺序处理打印任务,避免任务冲突

5. Web服务器并发请求限制

Semaphore requestSemaphore = new Semaphore(100, 100); // 同时处理的最大请求数为100async Task HandleHttpRequest(HttpRequest request)
{requestSemaphore.WaitOne();try{await ProcessRequestAsync(request); // 处理HTTP请求}finally{requestSemaphore.Release();}
}// Web服务器使用信号量限制同时处理的并发请求数量,防止过多请求导致系统过载

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

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

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

相关文章

Leetcode—1068. 产品销售分析 I【简单】

2024每日刷题(112) Leetcode—1068. 产品销售分析 I MySQL实现代码 # Write your MySQL query statement below SELECT Product.product_name,Sales.year,Sales.price FROM Sales INNER JOIN Product USING (product_id);运行结果 之后我会持续更新&am…

【stm32】hal库学习笔记-ADC模数转换(超详细!)

【stm32】hal库学习笔记-ADC模数转换(超详细!) 本篇章介绍了ADC实现电压检测的三种方式 ADC原理及选型 ADC将连续的模拟电压信号转换为二进制的数字信号 选型参数 速度(采样频率) 功耗 精度 转换原理 ADC hal库驱…

代码审计-CVE-2023-6654-PHPEMS-加密-解密分析

路由: 入口方法: 鉴权分析: 由此可以得出 鉴权是由session类负责获取参数后,由各个类的魔术方法负责:(在此还有一个方法 全局搜索登录关键词) 1、断点分析: 寻找鉴权点分析&#…

docker安装zpan

安装 1.创建数据库 docker run -di --namezpan_mysql -p 3309:3306 -e MYSQL_ROOT_PASSWORD123456 mysql 2.手动新建数据库zpan 3.创建目录 mkdir -p /opt/zpan cd /opt/zpan 4.编写配置文件 vim config.yml #详细配置文档可参考: https://zpan.space/#/zh…

八中友好教室1

题目 思路 我们可以在dfs遍历时顺便统计以每个节点为根的子树的节点个数,然后在回溯的时候判断如果以当前节点的子节点为根的子树的节点个数个数为偶数,说明这些点可以两两配对,所以当前节点与子节点之间不需要配对,否则的话就把…

代码随想录算法训练营29期|day41 任务以及具体任务

第九章 动态规划part03 343. 整数拆分 class Solution {public int integerBreak(int n) {//dp[i] 为正整数 i 拆分后的结果的最大乘积int[] dp new int[n1];dp[2] 1;for(int i 3; i < n; i) {for(int j 1; j < i-j; j) {// 这里的 j 其实最大值为 i-j,再大只不过是重…

保护个人信息安全,避免成为“互联网中的裸泳者”

⚽️ 一、互联网中的裸泳者&#x1f3c0; 二、代理 IP 的应用 - 解锁无限可能⚾️ 三、代理 ip 的几种类型 3.1 动态住宅代理&#xff08;Rotating Residential Proxy&#xff09;3.2 静态住宅代理&#xff08;Static Residential Proxy&#xff09;3.3 动态长效ISP&#xff08…

交友系统---让陌生人变成熟悉人的过程。APP小程序H5三端源码交付,支持二开。

随着社交网络的发展和普及&#xff0c;人们之间的社交模式正在发生着深刻的变革。传统的线下交友方式已经逐渐被线上交友取而代之。而同城交友正是这一趋势的产物&#xff0c;它利用移动互联网的便利性&#xff0c;将同城内的人们连接在一起&#xff0c;打破了时空的限制&#…

挖矿系列:细说Python、conda 和 pip 之间的关系

继续挖矿&#xff0c;挖金矿&#xff01; 1. Python、conda 和 pip Python、conda 和 pip 是在现代数据科学和软件开发中常用的工具&#xff0c;它们各自有不同的作用&#xff0c;但相互之间存在密切的关系&#xff1a; Python&#xff1a;是一种解释型、面向对象的高级程序设…

自定义Dockerfile构建运行springboot

自定义Dockerfile构建运行springboot 通过dockerfile生成自定义nginx镜像 &#xff01;&#xff01;&#xff01;docker 必须在linux环境下才能进行如果你是window则需要装虚拟机 新建一个文件名字为Dockerfile&#xff0c;无需后缀 文件完整名就是Dockerfile,也可以自定义d…

全新 鸿蒙系统

一&#xff0c; 开发框架 基础 二&#xff0c; 官网地址 文档开发&#xff1a;华为HarmonyOS智能终端操作系统官网 | 应用设备分布式开发者生态 三&#xff0c;基础了解 鸿蒙系统是基于 js 和 ts 衍生出来的一个东西 要学 arkts 就要学习 js 和 ts 语法 四&#xff0c…

《合成孔径雷达成像算法与实现》Figure6.4

clc clear close all参数设置 距离向参数设置 R_eta_c 20e3; % 景中心斜距 Tr 2.5e-6; % 发射脉冲时宽 Kr 20e12; % 距离向调频率 alpha_os_r 1.2; % 距离过采样率 Nrg 320; % 距离线采样数 距离向…