当前位置: 首页 > news >正文

信号量和事件及队列补充

【一】信号量(了解)

  • 信号量Semahpore(同线程一样)

【1】引入

  • 互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据

【2】例子

  • 比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去

  • Lock 锁住一个马桶,同时只能有一个人

  • Semaphore 锁住的是公共厕所,同时可以来一堆人

【3】示例

  • 如果指定信号量为3,那么来一个人获得一把锁,计数加1,当计数等于3时,后面的人均需要等待。

  • 一旦释放,就有人可以获得一把锁

信号量与进程池的概念很像,但是要区分开,信号量涉及到加锁的概念

from multiprocessing import Process, Semaphore
import time
import random
​
​
def go_wc(sem, user):# 【1】对信号量加锁,一个进程占用则锁池 -1sem.acquire()
​print(f'{user} 占到一个坑\n')# 模拟每一个人如厕的速度不一样,0代表没拉出来,直接出来了time.sleep(random.randint(0, 3))# 【2】释放信号量锁sem.release()print(f'{user} 站起来了\n')
​
​
if __name__ == '__main__':# 【一】创建一个信号量的池子sem = Semaphore(5)p_1 = []# 【二】十三个子进程for i in range(13):# 【三】创建子进程p = Process(target=go_wc, args=(sem, f"user {i}:",))# 【四】启动子进程p.start()# 【五】添加到进程列表p_1.append(p)# 等待所有子进程执行完毕for i in p_1:i.join()print('=======')user 0: 占到一个坑
​
user 2: 占到一个坑
​
user 1: 占到一个坑
​
user 1: 站起来了
​
user 4: 占到一个坑
​
user 3: 占到一个坑
​
user 6: 占到一个坑
​
user 2: 站起来了
​
user 5: 占到一个坑
​
user 0: 站起来了
​
user 8: 占到一个坑
​
user 4: 站起来了
​
user 7: 占到一个坑
​
user 6: 站起来了
​
user 10: 占到一个坑
user 9: 占到一个坑
​
user 3: 站起来了
​
​
user 10: 站起来了
​
user 11: 占到一个坑
​
user 8: 站起来了
​
user 12: 占到一个坑
​
user 12: 站起来了
​
user 5: 站起来了
​
user 7: 站起来了
​
user 11: 站起来了
​
user 9: 站起来了
​
=======

【二】事件

【1】什么是事件

  • Event(同线程一样)

【2】事件处理方法

  • python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。

  • 事件处理的机制:

    • 全局定义了一个“Flag”

    • 如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞

    • 如果“Flag”值为True,那么event.wait 方法时便不再阻塞。

    • clear:

      • 将“Flag”设置为False

    • set:

      • 将“Flag”设置为True

from multiprocessing import Process, Event, Manager
import time
import random
​
# 能给你的python解释器终端显示的内容上色
color_red = '\033[31m'
color_reset = '\033[0m'
color_green = '\033[32m'
​
​
# 定义车辆行为函数,它会根据事件对象(event)的状态来决定是否等待或通过路口
def car(event, n):'''模拟汽车行为:param event: 事件对象,用于同步操作,红绿灯状态的标识:param n: 第几辆车的标识:return: 无返回值'''
​# 创建一个无限循环直到车辆离开while True:# 如果事件未设置,表示红灯 Falseif not event.is_set():# 红灯亮时,车辆等待,并输出提示信息print(f'{color_red}红灯亮{color_reset},car{n} :>>> 正在等待 ... ')# 阻塞当前进程,等待event被设置(绿灯)event.wait()# 当event被设置后,打印绿灯信息print(f'{color_green}车 {n} :>>>> 看见绿灯亮了{color_reset}')# 模拟通过路口需要的时间time.sleep(random.randint(3, 6))# 防止在sleep期间event状态改变,再次检查状态if not event.is_set():continue# 通过路口print(f'car {n} :>>>> 安全通行')# 退出循环break
​
​
# 定义 警车 行为函数, 警车 在红灯时等待一秒后直接通过
def police_car(event, n):'''模拟 警车 行为:param event: 事件对象,用于同步操作,红绿灯状态的标识:param n: 第几辆车的标识:return: 无返回值'''while True:# 判断是否为红灯if not event.is_set():print(f'{color_red}红灯亮{color_reset},car{n} :>>> 正在等待 ... ')#  等待1秒,不完全遵守交通规则event.wait(1)print(f'灯的是{event.is_set()},警车走了,car{n}')# 通过后立即结束循环break
​
​
# 定义交通灯控制函数,周期性切换红绿灯状态
def traffic_lights(event, interval):'''模拟 交通灯 行为:param event: 事件对象,用于同步操作,红绿灯状态的标识:param interval: 间隔(比如10秒)改变信号灯:return: 无返回值'''# 无限循环,持续控制交通灯状态while True:# 按照给定间隔(比如10秒)改变信号灯time.sleep(interval)# 如果当前是绿灯if event.is_set():# 切换到红灯状态# event.is_set() ---->Falseevent.clear()else:# 如果当前是红灯,则切换到绿灯状态# event.is_set() ----> Trueevent.set()
​
​
def main():# 初始化事件对象,初始状态为清除(即红灯)event = Event()# 使用Manager创建一个可跨进程共享的Event对象# manager = Manager()# event = manager.Event()
​# 创建并启动多个 警车 进程# for i in range(5):#     police_car_process = Process(target=police_car, args=(event, i))#     police_car_process.start()for i in range(5):police_car_process = Process(target=car, args=(event, i))police_car_process.start()# 启动交通灯控制进程# 交通灯变化周期为10秒traffic_lights_process = Process(target=traffic_lights, args=(event, 10))traffic_lights_process.start()
​# 打印分割线,表明程序运行开始print(' ------------交通开始------------- ')
​
​
if __name__ == '__main__':main()#  ------------交通开始-------------# 红灯亮,car2 :>>> 正在等待 ...# 红灯亮,car0 :>>> 正在等待 ...# 红灯亮,car3 :>>> 正在等待 ...# 红灯亮,car1 :>>> 正在等待 ...# 红灯亮,car4 :>>> 正在等待 ...# 灯的是False,警车走了,car2# 灯的是False,警车走了,car0# 灯的是False,警车走了,car3# 灯的是False,警车走了,car1# 灯的是False,警车走了,car4
​# print("\033[31m这是红色文本\033[0m")  # 红色前景色# print("\033[32m这是绿色文本\033[0m")  # 绿色前景色# print("\033[1;33m这是加粗的黄色文本\033[0m")  # 加粗并设置黄色前景色# print("\033[44m这是蓝色背景文本\033[0m")  # 蓝色背景色# print("\033[34;47m这是蓝色前景色和白色背景色的文本\033[0m")  # 蓝色前景和白色背景

【三】队列补充

from queue import Queue, LifoQueue, PriorityQueue
​
# 【一】正常队列
# maxsize 过不给默认值,这个队列的容量就是无限大
# queue = Queue(5)
​
# 放
# queue.put(timeout=1)
# queue.put_nowait()
# 取
# queue.get(timeout=1)
# queue.get_nowait()
​
# 判断队列是否为空
# print(queue.empty())
# 判断是满的
# print(queue.full())
​
# 获取当前队列中的个数
# print(queue.qsize())
​
# 【一】Queue 先进先出
print(f'----------Queue-------------')
queue_normal = Queue(3)
queue_normal.put(1)
queue_normal.put(2)
queue_normal.put(3)
​
print(queue_normal.get())
print(queue_normal.get())
print(queue_normal.get())
# 【二】LifoQueue 后进先出
print(f'----------LifoQueue-------------')
queue_lifo = LifoQueue(3)
​
queue_lifo.put(1)
queue_lifo.put(2)
queue_lifo.put(3)
​
print(queue_lifo.get())
print(queue_lifo.get())
print(queue_lifo.get())
​
# 【三】PriorityQueue : 根据优先级数字越小的先出
print(f'----------PriorityQueue-------------')
queue_priority = PriorityQueue(3)
# 可以给放进队列的元素设置优先级:数字越小优先级越高!
queue_priority.put((50, 111))
queue_priority.put((0, 222))
queue_priority.put((100, 333))
​
print(queue_priority.get())
print(queue_priority.get())
print(queue_priority.get())
​
# (0, 222)
# (50, 111)
# (100, 333)

相关文章:

  • Linux-Web服务搭建面试题-1
  • esp32 idf开发中的常用命令
  • 网络故障排除-OSPF故障
  • 电脑找不到opencl.dll原因分析及5种详细的解决方法
  • 重生之 SpringBoot3 入门保姆级学习(02、打包部署)
  • 通关!游戏设计之道Day16
  • BFS解决最短路问题(详解)
  • C#控制台-输出输入、占位符
  • CSS基础(第二天)
  • 大模型日报2024-05-27
  • 算法训练营day41
  • 【学习笔记】计算机组成原理(七)
  • 10.SpringBoot 统一处理功能
  • 剪画小程序:分享3个无字幕保存高清视频的方法!!!
  • 211大学计算机专业不考408,新增的交叉专业却考408!南京农业大学计算机考研考情分析!
  • 2017 年终总结 —— 在路上
  • Invalidate和postInvalidate的区别
  • JavaScript实现分页效果
  • php中curl和soap方式请求服务超时问题
  • python 装饰器(一)
  • Selenium实战教程系列(二)---元素定位
  • SpingCloudBus整合RabbitMQ
  • vuex 学习笔记 01
  • 不上全站https的网站你们就等着被恶心死吧
  • 将回调地狱按在地上摩擦的Promise
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 我的面试准备过程--容器(更新中)
  • 译自由幺半群
  • 责任链模式的两种实现
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • ​一些不规范的GTID使用场景
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (备忘)Java Map 遍历
  • (十八)三元表达式和列表解析
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (转)可以带来幸福的一本书
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • .gitignore文件设置了忽略但不生效
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET Core IdentityServer4实战-开篇介绍与规划
  • .net oracle 连接超时_Mysql连接数据库异常汇总【必收藏】
  • .net 无限分类
  • .net连接oracle数据库
  • .Net中的设计模式——Factory Method模式
  • @ 代码随想录算法训练营第8周(C语言)|Day57(动态规划)
  • @Conditional注解详解
  • [12] 使用 CUDA 加速排序算法
  • [17]JAVAEE-HTTP协议
  • [20150629]简单的加密连接.txt
  • [2016.7 Day.4] T1 游戏 [正解:二分图 偏解:奇葩贪心+模拟?(不知如何称呼不过居然比std还快)]
  • [AX]AX2012 R2 出差申请和支出报告
  • [BROADCASTING]tensor的扩散机制
  • [C#小技巧]如何捕捉上升沿和下降沿
  • [CISCN2019 华北赛区 Day1 Web5]CyberPunk --不会编程的崽