- Python 基础
- Python - 首页
- Python - 概述
- Python - 历史
- Python - 特性
- Python vs C++
- Python - Hello World 程序
- Python - 应用领域
- Python - 解释器
- Python - 环境搭建
- Python - 虚拟环境
- Python - 基本语法
- Python - 变量
- Python - 数据类型
- Python - 类型转换
- Python - Unicode 系统
- Python - 字面量
- Python - 运算符
- Python - 算术运算符
- Python - 比较运算符
- Python - 赋值运算符
- Python - 逻辑运算符
- Python - 位运算符
- Python - 成员运算符
- Python - 身份运算符
- Python - 运算符优先级
- Python - 注释
- Python - 用户输入
- Python - 数字
- Python - 布尔值
- Python 控制语句
- Python - 控制流
- Python - 决策
- Python - if 语句
- Python - if else
- Python - 嵌套 if
- Python - match-case 语句
- Python - 循环
- Python - for 循环
- Python - for-else 循环
- Python - while 循环
- Python - break 语句
- Python - continue 语句
- Python - pass 语句
- Python - 嵌套循环
- Python 函数与模块
- Python - 函数
- Python - 默认参数
- Python - 关键字参数
- Python - 仅限关键字参数
- Python - 位置参数
- Python - 仅限位置参数
- Python - 可变参数
- Python - 变量作用域
- Python - 函数注解
- Python - 模块
- Python - 内置函数
- Python 字符串
- Python - 字符串
- Python - 字符串切片
- Python - 修改字符串
- Python - 字符串连接
- Python - 字符串格式化
- Python - 转义字符
- Python - 字符串方法
- Python - 字符串练习
- Python 列表
- Python - 列表
- Python - 访问列表元素
- Python - 修改列表元素
- Python - 添加列表元素
- Python - 删除列表元素
- Python - 循环遍历列表
- Python - 列表推导式
- Python - 排序列表
- Python - 复制列表
- Python - 合并列表
- Python - 列表方法
- Python - 列表练习
- Python 元组
- Python - 元组
- Python - 访问元组元素
- Python - 更新元组
- Python - 解包元组
- Python - 循环遍历元组
- Python - 合并元组
- Python - 元组方法
- Python - 元组练习
- Python 集合
- Python - 集合
- Python - 访问集合元素
- Python - 添加集合元素
- Python - 删除集合元素
- Python - 循环遍历集合
- Python - 合并集合
- Python - 复制集合
- Python - 集合运算符
- Python - 集合方法
- Python - 集合练习
- Python 字典
- Python - 字典
- Python - 访问字典元素
- Python - 修改字典元素
- Python - 添加字典元素
- Python - 删除字典元素
- Python - 字典视图对象
- Python - 循环遍历字典
- Python - 复制字典
- Python - 嵌套字典
- Python - 字典方法
- Python - 字典练习
- Python 数组
- Python - 数组
- Python - 访问数组元素
- Python - 添加数组元素
- Python - 删除数组元素
- Python - 循环遍历数组
- Python - 复制数组
- Python - 反转数组
- Python - 排序数组
- Python - 合并数组
- Python - 数组方法
- Python - 数组练习
- Python 文件处理
- Python - 文件处理
- Python - 写入文件
- Python - 读取文件
- Python - 重命名和删除文件
- Python - 目录
- Python - 文件方法
- Python - OS 文件/目录方法
- Python - OS 路径方法
- 面向对象编程
- Python - OOPs 概念
- Python - 类与对象
- Python - 类属性
- Python - 类方法
- Python - 静态方法
- Python - 构造函数
- Python - 访问修饰符
- Python - 继承
- Python - 多态
- Python - 方法重写
- Python - 方法重载
- Python - 动态绑定
- Python - 动态类型
- Python - 抽象
- Python - 封装
- Python - 接口
- Python - 包
- Python - 内部类
- Python - 匿名类和对象
- Python - 单例类
- Python - 包装类
- Python - 枚举
- Python - 反射
- Python 错误与异常
- Python - 语法错误
- Python - 异常
- Python - try-except 块
- Python - try-finally 块
- Python - 抛出异常
- Python - 异常链
- Python - 嵌套 try 块
- Python - 用户自定义异常
- Python - 日志记录
- Python - 断言
- Python - 内置异常
- Python 多线程
- Python - 多线程
- Python - 线程生命周期
- Python - 创建线程
- Python - 启动线程
- Python - 等待线程结束
- Python - 线程命名
- Python - 线程调度
- Python - 线程池
- Python - 主线程
- Python - 线程优先级
- Python - 守护线程
- Python - 线程同步
- Python 同步
- Python - 线程间通信
- Python - 线程死锁
- Python - 中断线程
- Python 网络编程
- Python - 网络编程
- Python - 套接字编程
- Python - URL 处理
- Python - 泛型
- Python 库
- NumPy 教程
- Pandas 教程
- SciPy 教程
- Matplotlib 教程
- Django 教程
- OpenCV 教程
- Python 杂项
- Python - 日期与时间
- Python - 数学
- Python - 迭代器
- Python - 生成器
- Python - 闭包
- Python - 装饰器
- Python - 递归
- Python - 正则表达式
- Python - PIP
- Python - 数据库访问
- Python - 弱引用
- Python - 序列化
- Python - 模板
- Python - 输出格式化
- Python - 性能测量
- Python - 数据压缩
- Python - CGI 编程
- Python - XML 处理
- Python - GUI 编程
- Python - 命令行参数
- Python - 文档字符串
- Python - JSON
- Python - 发送邮件
- Python - 扩展
- Python - 工具/实用程序
- Python - GUIs
- Python 高级概念
- Python - 抽象基类
- Python - 自定义异常
- Python - 高阶函数
- Python - 对象内部机制
- Python - 内存管理
- Python - 元类
- Python - 使用元类进行元编程
- Python - 模拟和桩
- Python - Monkey Patching
- Python - 信号处理
- Python - 类型提示
- Python - 自动化教程
- Python - Humanize 包
- Python - 上下文管理器
- Python - 协程
- Python - 描述符
- Python - 诊断和修复内存泄漏
- Python - 不可变数据结构
- Python 有用资源
- Python - 问答
- Python - 在线测试
- Python - 快速指南
- Python - 参考
- Python - 速查表
- Python - 项目
- Python - 有用资源
- Python - 讨论
- Python 编译器
- NumPy 编译器
- Matplotlib 编译器
- SciPy 编译器
Python - 线程间通信
线程间通信是指在 Python 多线程程序中启用线程之间通信和同步的过程。
通常,Python 中的线程共享进程中的同一内存空间,这允许它们通过共享变量、对象和threading模块提供的专用同步机制来交换数据并协调其活动。
为了促进线程间通信,threading 模块提供了各种同步原语,例如锁、事件、条件和信号量对象。在本教程中,您将学习如何使用 Event 和 Condition 对象在多线程程序中实现线程间的通信。
Event 对象
Event 对象管理内部标志的状态,以便线程可以等待或设置。Event对象提供控制此标志状态的方法,允许线程基于共享条件同步其活动。
该标志最初为假,使用 set() 方法设置为真,使用 clear() 方法重置为假。wait() 方法会阻塞,直到标志为真。
以下是Event对象的关键方法:
- is_set():当且仅当内部标志为真时返回 True。
- set():将内部标志设置为真。所有等待它变为真的线程都会被唤醒。一旦标志为真,调用 wait() 的线程根本不会阻塞。
- clear():将内部标志重置为假。随后,调用 wait() 的线程将阻塞,直到调用 set() 将内部标志再次设置为真。
- wait(timeout=None):阻塞直到内部标志为真。如果在进入时内部标志为真,则立即返回。否则,阻塞直到另一个线程调用 set() 将标志设置为真,或直到可选超时发生。当存在 timeout 参数且不为 None 时,它应该是一个浮点数,以秒为单位指定操作的超时时间。
示例
以下代码尝试模拟由交通信号灯状态(绿色或红色)控制的交通流量。
程序中有两个线程,它们分别针对两个不同的函数。signal_state() 函数定期设置和重置事件,表示信号从绿色变为红色。
traffic_flow() 函数等待事件被设置,并在事件保持设置状态时运行循环。
from threading import Event, Thread import time terminate = False def signal_state(): global terminate while not terminate: time.sleep(0.5) print("Traffic Police Giving GREEN Signal") event.set() time.sleep(1) print("Traffic Police Giving RED Signal") event.clear() def traffic_flow(): global terminate num = 0 while num < 10 and not terminate: print("Waiting for GREEN Signal") event.wait() print("GREEN Signal ... Traffic can move") while event.is_set() and not terminate: num += 1 print("Vehicle No:", num," Crossing the Signal") time.sleep(1) print("RED Signal ... Traffic has to wait") event = Event() t1 = Thread(target=signal_state) t2 = Thread(target=traffic_flow) t1.start() t2.start() # Terminate the threads after some time time.sleep(5) terminate = True # join all threads to complete t1.join() t2.join() print("Exiting Main Thread")
输出
执行上述代码后,您将获得以下输出:
Waiting for GREEN Signal Traffic Police Giving GREEN Signal GREEN Signal ... Traffic can move Vehicle No: 1 Crossing the Signal Traffic Police Giving RED Signal RED Signal ... Traffic has to wait Waiting for GREEN Signal Traffic Police Giving GREEN Signal GREEN Signal ... Traffic can move Vehicle No: 2 Crossing the Signal Vehicle No: 3 Crossing the Signal Traffic Police Giving RED Signal Traffic Police Giving GREEN Signal Vehicle No: 4 Crossing the Signal Traffic Police Giving RED Signal RED Signal ... Traffic has to wait Traffic Police Giving GREEN Signal Traffic Police Giving RED Signal Exiting Main Thread
Condition 对象
Python 的threading模块中的 Condition 对象提供了一种更高级的同步机制。它允许线程在继续执行之前等待来自另一个线程的通知。Condition 对象始终与锁相关联,并提供线程间信号机制。
以下是 threading.Condition() 类的语法:
threading.Condition(lock=None)
以下是 Condition 对象的关键方法:
- acquire(*args):获取底层锁。此方法调用底层锁上的相应方法;返回值是该方法返回的任何内容。
- release():释放底层锁。此方法调用底层锁上的相应方法;没有返回值。
- wait(timeout=None): 此方法释放底层锁,然后阻塞,直到另一个线程对同一个条件变量调用 notify() 或 notify_all() 方法唤醒它,或者直到可选的超时发生。一旦被唤醒或超时,它会重新获取锁并返回。
- wait_for(predicate, timeout=None): 此实用程序方法可能会重复调用 wait(),直到满足谓词或发生超时。返回值是谓词的最后返回值,如果方法超时则将评估为 False。
- notify(n=1): 此方法最多唤醒 n 个等待条件变量的线程;如果没有任何线程正在等待,则此方法什么也不做。
- notify_all(): 唤醒所有等待此条件的线程。此方法类似于 notify(),但它会唤醒所有等待线程,而不是一个线程。如果调用线程在调用此方法时未获取锁,则会引发 RuntimeError。
示例
此示例演示了使用 Python threading 模块的 Condition 对象进行线程间通信的一种简单形式。这里 thread_a 和 thread_b 使用 Condition 对象进行通信,thread_a 等待直到收到来自 thread_b 的通知。thread_b 休眠 2 秒后通知 thread_a,然后结束。
from threading import Condition, Thread import time c = Condition() def thread_a(): print("Thread A started") with c: print("Thread A waiting for permission...") c.wait() print("Thread A got permission!") print("Thread A finished") def thread_b(): print("Thread B started") with c: time.sleep(2) print("Notifying Thread A...") c.notify() print("Thread B finished") Thread(target=thread_a).start() Thread(target=thread_b).start()
输出
执行上述代码后,您将获得以下输出:
Thread A started Thread A waiting for permission... Thread B started Notifying Thread A... Thread B finished Thread A got permission! Thread A finished
示例
这是另一个代码示例,演示了如何使用 Condition 对象在线程之间进行通信。在这个例子中,线程 t2 运行 taskB() 函数,线程 t1 运行 taskA() 函数。t1 线程获取条件并发出通知。
此时,t2 线程处于等待状态。条件释放后,等待线程继续使用通知函数生成的随机数。
from threading import Condition, Thread import time import random numbers = [] def taskA(c): for _ in range(5): with c: num = random.randint(1, 10) print("Generated random number:", num) numbers.append(num) print("Notification issued") c.notify() time.sleep(0.3) def taskB(c): for i in range(5): with c: print("waiting for update") while not numbers: c.wait() print("Obtained random number", numbers.pop()) time.sleep(0.3) c = Condition() t1 = Thread(target=taskB, args=(c,)) t2 = Thread(target=taskA, args=(c,)) t1.start() t2.start() t1.join() t2.join() print("Done")
执行此代码时,将产生以下输出:
waiting for update Generated random number: 2 Notification issued Obtained random number 2 Generated random number: 5 Notification issued waiting for update Obtained random number 5 Generated random number: 1 Notification issued waiting for update Obtained random number 1 Generated random number: 9 Notification issued waiting for update Obtained random number 9 Generated random number: 2 Notification issued waiting for update Obtained random number 2 Done