103、Python并发编程:使用信号量Semaphore实现资源有限的并发场景

引言

在前面几篇文章的基础上,应对并发编程中现成同步的需求场景:

我们可以使用锁,作为多线程同步的几个核心基础,实现对临界资源的保护,确保满足基本的互斥访问逻辑。

使用条件变量Condition,实现有固定顺序的复杂交互场景下的同步协作。

使用队列Queue,实现简单的消息中间件,支持生产者消费者模型,实现了多个工作环节的解耦、协作。

但是,如果资源有限的场景中,如何处理并发的同步呢?比如银行柜台只有5个窗口,最多同时服务5个客户,但是可能有20个客户在排队等待。比如,高铁站,只有6个检票通道,但是有500个旅客等待进展……

这就要用到本文的主角,信号量Semaphore了。

本文的主要内容有:

1、信号量的概念

2、信号量的使用场景

3、Python中Semaphore的设计及使用实例

信号量的概念

信号量(semaphore)是一种用于控制对共享资源访问的同步机制,多线程环境中,信号量可以用于限制同时访问某种资源的线程数量。

信号量,可以简单理解为一个计数器,它用于保护对有限资源的并发访问,通常来说这种有限资源是可以复用的,而不是消耗型的。

Python中的Semaphore可以实现信号量的支持。

信号量的使用,一般遵循如下规则:

1、每个线程在访问共享资源之前,必须先“获取”信号量,一般称为P操作,使其计数器减一。

2、使用完毕后,“释放”信号量,一般称为V操作,使计数器加一。

3、当计数器为零时,获取信号量的线程将阻塞,直到其他线程释放信号量。

信号量的使用场景

信号量的使用场景,一般是资源有限的并发场景下,对这些有限的共享资源的共享、复用。

通常可以将信号量应用于如下场景中:

1、流量控制:限制高并发场景中对某些关键部分的访问流量,防止系统过载。

2、限制有限资源的访问:信号量可以用于限制同时访问特定资源(比如数据库连接、文件读写、网络带宽等)的线程数量。

3、多生产者多消费者模式:可以用信号量协调多生产者多消费者的同步访问场景。

4、互斥锁的泛化:在某些情况下,可以将信号量看作是一个允许多个现成访问而不是单个线程的互斥锁。

基于信号量,可以更加便捷实现在实际工作中比较熟知的一些设计模式或者应用组件,比如:数据库连接池、线程池等。

Python中Semaphore的设计及使用实例

Semaphore的设计实现

首先通过Semaphore的相关文档说明,来看下Python中Semaphore的设计实现:

9f9ddbbda8769881fe424504c53edf8a.jpeg

9924b79e56319e64bc49e0d346447b70.jpeg

c0f50350a34ecd8abdb7ab725c82b07e.jpeg

从Python中关于Semaphore源码可以看到该对象的设计实现:

1、通过计数器维持现有资源的数量,如果不指定资源数量,默认为1,也就退化成了一个互斥锁。

2、通过持有锁对象,确保对计数器的修改是原子操作,防止竞态条件。

3、通过持有条件变量Condition对象,来管理阻塞和唤醒等待资源的线程。

4、通过acquire()方法,实现对信号量的P操作,如果信号量的内部计数器大于0,则计数器减1;如果计数器为0,则阻塞,直至计数器大于0。

5、通过release()方法,实现对信号量的V操作,将信号量内部计数器加1,并唤醒一个阻塞在P操作上的线程(如果有的话)。

6、Semaphore对象实现了上下文管理的__enter__()和__exit__()魔术方法,所以可以通过with语法糖进行便捷的管理。

使用实例

我们通过Semaphore简单模拟一下银行柜员在柜台服务客户的业务场景:

1、有5个柜台,相应的有5个银行柜员提供业务服务。

2、共有50个客户需要在柜台办理各种业务。

直接看代码:

from threading import Thread, Semaphore
import timeclass Bank:def __init__(self, max_counter):self.counter = Semaphore(max_counter)def service(self, customer):print(f'客户{customer}需要办理业务')with self.counter:print(f'====有柜台空闲,开始接待{customer},办理相关业务===')# 模拟服务time.sleep(1)print('业务办理完成')def customer_business(bank, customer):bank.service(customer)if __name__ == '__main__':bank = Bank(5)customers = [Thread(target=customer_business, args=(bank, f'客户{i}')) for i in range(50)]for customer in customers:customer.start()for customer in customers:customer.join()

执行结果:

刚开始启动,由于只有5个柜台,所以0-4号顾客直接进行业务办理了,之后的客户要等待了。

f4c343fbdfd47fcfd04405fe956d54fb.jpeg

后续有业务办理完成,柜台空闲,则继续服务后面的客户:

d3b5353cad48f980c982ef0e86f97384.jpeg

总结

本文首先回顾了之前介绍到的锁、条件变量和队列各自所能应对的并发同步场景,引出了资源有限的同步场景中的主角Semaphore,分别介绍了Semaphore的设计实现及使用案例。

感谢您的拨冗阅读。

a7bf8d4fd630aab6d636bcf031f0c774.jpeg

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

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

相关文章

蛋奶烙饼:美味与温暖的邂逅

食家巷蛋奶烙饼,那金黄的色泽、浓郁的奶香和蛋香,光是看着就让人垂涎欲滴。它的制作过程并不复杂,却充满了生活的烟火气。将面粉、鸡蛋、牛奶等简单的食材混合在一起,搅拌成细腻的面糊。在平底锅中倒入少许油,舀一勺面…

Linux内核中IRQ Domain的结构、操作及映射机制详解

往期内容 本专栏往期内容,interrtupr子系统: 深入解析Linux内核中断管理:从IRQ描述符到irq domain的设计与实现 pinctrl和gpio子系统专栏: 专栏地址:pinctrl和gpio子系统 编写虚拟的GPIO控制器的驱动程序:…

cocos creator 3.8.3物理组件分组的坑

坑,坑的不行的大坑 group用的二进制的左移获取十进制的数值 目前是这样判断的,也不知道对不对,什么get、set Group没找到

如何解决“在ANACONDA prompt可以使用‘conda activate‘,但是在pycharm终端没办法使用该指令“”

一、设置好环境变量 此电脑(右键)-属性-高级系统设置-环境变量-在系统变量那一筐的PATH双击添加 二、完成后再测试conda activate 笔者测试完后,conda是可以用了,但是conda activate用不了。 显示该错误CommandNotFoundError:…

三菱MR-J4-B系列伺服参数一览

要点 与伺服系统控制器连接后,同服系统控制器的伺服参数的值即被写入各参数中。根据伺服系统控制器的机种和伺服放大器软件版本及MRConfigurator2的软件版本,存在无法设定的参数或范围。详细内容请参照伺服系统控制器的用户手册。请使用MR Configurator2…

Pattern program MPAT 详解

本文为VIP文章,主要介绍Pattern中元素与格式、常用指令、地址&数据产生指令等。 目录 一、pattern概述 二:Pattern构成元素 1、pattern构成元素:MPAT、END 2、pattern构成元素:pattern file name 3、pattern构成元素:SDEF 4、Pattern构成元素:REGISETR 5、Pa…

Qt编译lua库并调用

参考博客: 编译lua库 参考下面文章编译lua库文件 QT5.9学习笔记之QT编译lua库_qtluaintf.h-CSDN博客 https://blog.csdn.net/qq_23345187/article/details/112710677 Qt代码引用lua库文件 打开pro项目文件,右键空白处,点击添加库&#xff…

数据结构:直接插入排序

直接插入排序是数据结构中较为简单的插入排序法,基本思想是:把待排序的记录按照关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插完为止,得到一个新的有序序列。 实际上我们玩扑克时,就用了插入排…

Pr 视频过渡:溶解

效果面板/视频过渡/溶解 Video Transitions/Dissolve Adobe Premiere Pro 的视频过渡效果中,溶解 Dissolve效果组提供了多种平滑过渡方式,适用于不同的场景需求,从基础的淡入淡出到复杂的叠加溶解,帮助用户实现更具层次感的视觉过…

使用 Elasticsearch 构建食谱搜索(一)

作者:来自 Elastic Andre Luiz 了解如何使用 Elasticsearch 构建基于语义搜索的食谱搜索。 简介 许多电子商务网站都希望增强其食谱搜索体验。正确使用语义搜索可以让客户根据更自然的查询(例如 “something for Valentines Day - 情人节的礼物” 或 “…

prompt资料收集

1. LANGgpt模板 # Role: 知识探索专家 ## Profile: - - 即刻App即刻App,享受探索、表达和创造https://m.okjike.com/originalPosts/649801f1ba47fe581a0da471?seyJ1IjoiNjQyM2IwMDE4NDg5Njk1NGJjYzhkNWU1IiwiZCI6MX0%3D2. 好的prompt的标准 主观的说:…

大数据学习10之Hive高级

1.Hive高级 将大的文件按照某一列属性进行GROUP BY 就是分区,只是默认开窗存储; 分区是按行,如一百行数据,按十位上的数字分区,则有十个分区,每个分区里有十行; 分桶是根据某个字段哈希对桶数取…

前端Nginx的安装与应用

目录 一、前端跨域方式 1.1、CORS(跨域资源共享) 1.2、JSONP(已过时) 1.3、WebSocket 1.4、PostMessage 1.5、Nginx 二、安装 三、应用 四、命令 4.1、基本操作命令 4.2、nginx.conf介绍 4.2.1、location模块 4.2.2、反向代理配置 4.2.3、负载均衡模块 4.2.4、通…

Mit6.S081-实验环境搭建

Mit6.S081-实验环境搭建 注:大家每次做一些操作的时候觉得不太保险就先把虚拟机克隆一份 前言 qemu(quick emulator):这是一个模拟硬件环境的软件,利用它可以运行我们编译好的操作系统。 准备一个Linux系统&#xf…

AWS账号安全:如何防范与应对账号被盗风险

在云计算时代,Amazon Web Services(AWS)作为全球领先的云服务提供商,为企业和个人提供了强大的计算资源和灵活的服务。然而,随着云计算的普及,AWS账号被盗的风险也随之增加。我们九河云有多年用云经验&…

IPTABLE:Linux下的网络防火墙

IPTABLE:Linux下的网络防火墙 引言 在Linux系统中,IPtable是一种强大的网络防火墙工具,广泛应用于各种网络环境中。它不仅可以实现基本的包过滤功能,还能进行网络地址转换(NAT)、数据包记录、流量统计等高…

Java版工程行业管理系统源码-专业的工程管理软件- 工程项目各模块及其功能点清单

工程项目管理软件(工程项目管理系统)对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营,全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&am…

友思特应用 | 动态捕捉:高光谱相机用于移动产线上的食品检测

导读 高光谱成像技术能够为食品安全助力。以友思特BlackIndustry SWIR 1.7 Max 为代表的高光谱相机,完美解决了移动产线检测的应用难点。 高光谱技术:为食品安全保驾护航 食品安全一直是大众关心的热点话题,提供安全、高质量的食品需要对食…

Java——》try-with-resource

推荐链接: 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Kafka】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 总结——》【Linux】 总结——》【MongoD…

【极客兔兔-Web框架Gee详解】Day0 序言

文章目录 一、Web 开发1. 什么是Web 开发?2. 主要组成部分2.1 前端开发2.2 后端开发2.3 全栈开发2.4 数据库管理 3. Web开发过程3.1 规划和设计:3.2 开发和编码:3.3 测试和优化:3.4 部署和维护: 4. 总结 二、用标准库n…