Python Event实现线程通信
2023-06-13 09:12:02 时间
Event 是一种非常简单的线程通信机制,一个线程发出一个 Event,另一个线程可通过该 Event 被触发。
clear():该方法将 Event 的内部旗标设置为 False,通常接下来会调用 wait() 方法来阻塞当前线程。 wait(timeout=None):该方法会阻塞当前线程。
Event 本身管理一个内部旗标,程序可以通过 Event 的 set() 方法将该旗标设置为 True,也可以调用 clear() 方法将该旗标设置为 False。程序可以调用 wait() 方法来阻塞当前线程,直到 Event 的内部旗标被设置为 True。
Event 提供了如下方法:
clear():该方法将 Event 的内部旗标设置为 False,通常接下来会调用 wait() 方法来阻塞当前线程。 wait(timeout=None):该方法会阻塞当前线程。
下面程序示范了 Event 最简单的用法:
import threading import time event = threading.Event() def cal(name): # 等待事件,进入等待阻塞状态 print( %s 启动 % threading.currentThread().getName()) print( %s 准备开始计算状态 % name) event.wait() # ① # 收到事件后进入运行状态 print( %s 收到通知了. % threading.currentThread().getName()) print( %s 正式开始计算! % name) # 创建并启动两条,它们都会①号代码处等待 threading.Thread(target=cal, args=( 甲 , )).start() threading.Thread(target=cal, args=( 乙 , )).start() time.sleep(2) #② print( ------------------ ) # 发出事件 print( 主线程发出事件 ) event.set()
上面程序以 cal() 函数为 target,创建并启动了两个线程。由于 cal() 函数在 ① 号代码处调用了 Event 的 wait(),因此两个线程执行到 ① 号代码处都会进入阻塞状态;即使主线程在 ② 号代码处被阻塞,两个子线程也不会向下执行。
直到主程序执行到最后一行,程序调用了 Event 的 set() 方法将 Event 的内部旗标设直为 True,并唤醒所有等待的线程,这两个线程才能向下执行。
运行上面程序,将看到如下输出结果:
Thread-1 启动
甲 准备开始计算状态
Thread-2 启动
乙 准备开始计算状态
主线程发出事件
Thread-1 收到通知了.
Thread-2 收到通知了.
甲 正式开始计算!
乙 正式开始计算!
上面程序还没有使用 Event 的内部旗标,如果结合 Event 的内部旗标,同样可实现前面的 Account 的生产者-消费者效果:存钱线程(生产者)存钱之后,必须等取钱线程(消费者)取钱之后才能继续向下执行。
Event 实际上优点类似于 Condition 和旗标的结合体,但 Event 本身并不带 Lock 对象,因此如果要实现线程同步,还需要额外的 Lock 对象。
下面是使用 Event 改写后的 Account:
import threading class Account: # 定义构造器 def __init__(self, account_no, balance): # 封装账户编号、账户余额的两个成员变量 self.account_no = account_no self._balance = balance self.lock = threading.Lock() self.event = threading.Event() # 因为账户余额不允许随便修改,所以只为self._balance提供getter方法 def getBalance(self): return self._balance # 提供一个线程安全的draw()方法来完成取钱操作 def draw(self, draw_amount): # 加锁 self.lock.acquire() # 如果Event内部旗标为True,表明账户中已有人存钱进去 if self.event.is_set(): # 执行取钱操作 print(threading.current_thread().name + 取钱: + str(draw_amount)) self._balance -= draw_amount print( 账户余额为: + str(self._balance)) # 将Event内部旗标设为False self.event.clear() # 释放加锁 self.lock.release() # 阻塞当前线程阻塞 self.event.wait() else: # 释放加锁 self.lock.release() # 阻塞当前线程阻塞 self.event.wait() def deposit(self, deposit_amount): # 加锁 self.lock.acquire() # 如果Event内部旗标为False,表明账户中还没有人存钱进去 if not self.event.is_set(): # 执行存款操作 print(threading.current_thread().name/ + 存款: + str(deposit_amount)) self._balance += deposit_amount print( 账户余额为: + str(self._balance)) # 将Event内部旗标设为True self.event.set() # 释放加锁 self.lock.release() # 阻塞当前线程阻塞 self.event.wait() else: # 释放加锁 self.lock.release() # 阻塞当前线程阻塞 self.event.wait()
24042.html
python相关文章
- python整除和取余写法_Python的整除和取余[通俗易懂]
- python安装不了whl文件_Python安装whl文件过程图解
- python的命名规则_python命名规则[通俗易懂]
- 手机python 3.8解释器_Python 3.8 解释器安装教程
- json转字符串 python_Python读取json
- Python元组_python元组的定义方式
- 【说站】python线程通信Condition提供的方法
- 【说站】python线程阻塞的解决
- 【说站】python用circle函数画兔子的方法
- Python标识符的命名规则,下列哪些是对的?_python标识符不能使用关键字
- python读取pkl_Python读取文件的一段内容
- uwsgi部署django_django调用python脚本
- 【Python深度学习之路】-2.1 机器学习的流程
- python图像多层小波分解_Python中图像小波分解与重构以及灰度图加噪
- python 图像处理库_Python图像处理库
- 下列python语句的输出结果是print_下列 Python语句的输出结果是「建议收藏」
- Python自定义模块
- python实现线程池详解编程语言
- Python 进程线程协程 GIL 闭包 与高阶函数(五)详解编程语言
- Python 的加密库入门
- python驱动使用pip安装MySQL Python驱动的简单步骤(pip安装mysql)
- 利用Neo4j和Python进行无缝图形数据库支持(neo4j python)