python线程条件变量Condition(31)
对于线程与线程之间的交互我们在前面的文章已经介绍了 python 互斥锁Lock / python事件Event , 今天继续介绍一种线程交互方式 – 线程条件变量Condition.

一.线程条件变量Condition相关函数介绍
acquire() — 线程锁,注意线程条件变量Condition中的所有相关函数使用必须在acquire() /release() 内部操作;
release() — 释放锁,注意线程条件变量Condition中的所有相关函数使用必须在acquire() /release() 内部操作;
wait(timeout) — 线程挂起(阻塞状态),直到收到一个notify通知或者超时才会被唤醒继续运行(超时参数默认不设置,可选填,类型是浮点数,单位是秒)。wait()必须在已获得Lock前提下才能调用,否则会触发RuntimeError;
notify(n=1) — 通知其他线程,那些挂起的线程接到这个通知之后会开始运行,缺省参数,默认是通知一个正等待通知的线程,最多则唤醒n个等待的线程。notify()必须在已获得Lock前提下才能调用,否则会触发RuntimeError,notify()不会主动释放Lock;
notifyAll() — 如果wait状态线程比较多,notifyAll的作用就是通知所有线程;

二.线程条件变量Condition原理
在前面的文章已经介绍过互斥锁,主要作用是并行访问共享资源时,保护共享资源,防止出现脏数据。python 条件变量Condition也需要关联互斥锁,同时Condition自身提供了wait/notify/notifyAll方法,用于阻塞/通知其他并行线程,可以访问共享资源了。可以这么理解,Condition提供了一种多线程通信机制,假如线程1需要数据,那么线程1就阻塞等待,这时线程2就去制造数据,线程2制造好数据后,通知线程1可以去取数据了,然后线程1去获取数据。

三.线程条件变量Condition使用
案例一:成语接龙
# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@Author:何以解忧
@Blog(个人博客地址): shuopython.com
@WeChat Official Account(微信公众号):猿说python
@Github:www.github.com @File:python_.py
@Time:2019/10/21 21:25 @Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
""" # 导入线程模块
import threading # 创建条件变量condition
con = threading.Condition() def thread_one(name):
# 条件变量condition 线程上锁
con.acquire() print("{}:成语接龙准备好了吗".format(name))
# 唤醒正在等待(wait)的线程
con.notify() # 等待对方回应消息,使用wait阻塞线程,等待对方通过notify唤醒本线程
con.wait()
print("{}:一干二净".format(name))
# 唤醒对方
con.notify() # 等待消息答应
con.wait()
print("{}:一天就知道看抖音美女,给你来个简单点的,来了:毛手毛脚".format(name))
# 唤醒对方
con.notify() # 等待消息答应
con.wait()
print("{}:哟哟哟,不错不错!".format(name))
# 唤醒对方
con.notify() # 条件变量condition 线程释放锁
con.release() def thread_two(name):
# 条件变量condition 线程上锁
con.acquire() # wait阻塞状态,等待其他线程通过notify唤醒本线程
con.wait()
print("{}:准备好了~开始吧!".format(name))
# 唤醒对方
con.notify() # 等待消息答应
con.wait()
print("{}:净你妹啊,没法接...来个简单点的...".format(name))
# 唤醒对方
con.notify() # 等待消息答应
con.wait()
print("{}:嘿,这个我知道:脚踏实地".format(name))
# 唤醒对方
con.notify() con.release() if __name__ == "__main__": # 创建并初始化线程
t1 = threading.Thread(target=thread_one,args=("A"))
t2 = threading.Thread(target=thread_two,args=("B")) # 启动线程 -- 注意线程启动顺序,启动顺序很重要
t2.start()
t1.start() # 阻塞主线程,等待子线程结束
t1.join()
t2.join() print("程序结束!")
输出结果:
A:成语接龙准备好了吗
B:准备好了~开始吧!
A:一干二净
B:净你妹啊,没法接...来个简单点的...
A:一天就知道看抖音美女,给你来个简单点的,来了:毛手毛脚
B:嘿,这个我知道:脚踏实地
A:哟哟哟,不错不错!
程序结束!

案例二:生产者与消费者模式,以吃火锅为例:一盘老肉片有10块肉,吃完了又重新往锅里加….
生产者:往锅里加老肉片,每次加一盘(10块);
消费者:吃煮熟的肉片,没吃一片,肉片数量减一,吃完为止;
# 导入线程模块
import threading
import time # 创建条件变量condition
con = threading.Condition()
meat_num = 0 def thread_consumers():
# 条件变量condition 线程上锁
con.acquire() # 全局变量声明关键字 global
global meat_num
meat_num = 0 # 等待肉片下锅煮熟
con.wait()
while True:
print("我来一块肉片...")
meat_num -= 1
print("剩余肉片数量:%d"%meat_num)
time.sleep(0.5)
if meat_num == 0:
# 肉片吃光了,通知老板添加肉片
print("老板,再来一份老肉片...")
con.notify()
# 肉片吃光了,等待肉片
con.wait() # 条件变量condition 线程释放锁
con.release() def thread_producer():
# 条件变量condition 线程上锁
con.acquire()
# 全局变量声明关键字 global
global meat_num # 肉片熟了,可以开始吃了
meat_num = 10
print("肉片熟了,可以开始吃了...")
con.notify()
while True:
# 阻塞函数,等待肉片吃完的通知
con.wait()
meat_num = 10
# 添加肉片完成,可以继续开吃
print("添加肉片成功!当前肉片数量:%d"%meat_num)
time.sleep(1)
con.notify() con.release() if __name__ == "__main__":
# 创建并初始化线程
t1 = threading.Thread(target=thread_producer)
t2 = threading.Thread(target=thread_consumers) # 启动线程 -- 注意线程启动顺序,启动顺序很重要
t2.start()
t1.start() # 阻塞主线程,等待子线程结束
t1.join()
t2.join() print("程序结束!")
输出结果:
肉片熟了,可以开始吃了...
我来一块肉片...
剩余肉片数量:9
我来一块肉片...
剩余肉片数量:8
我来一块肉片...
剩余肉片数量:7
我来一块肉片...
剩余肉片数量:6
我来一块肉片...
剩余肉片数量:5
我来一块肉片...
剩余肉片数量:4
我来一块肉片...
剩余肉片数量:3
我来一块肉片...
剩余肉片数量:2
我来一块肉片...
剩余肉片数量:1
我来一块肉片...
剩余肉片数量:0
老板,再来一份老肉片...
添加肉片成功!当前肉片数量:10
我来一块肉片...
剩余肉片数量:9
我来一块肉片...
剩余肉片数量:8
我来一块肉片...
剩余肉片数量:7
.............
注意:
1.全局变量要声明关键字 global;
2.注意线程的启动顺序,这个很重要;
四.重点总结
注意线程互斥锁Lock/线程事件Event/线程条件变量Condition三者的区别,场景不同,使用方式也不同,前两者一般可以作为简单的线程交互,线程条件变量Condition可以用于比较复杂的线程交互!
猜你喜欢:
转载请注明:猿说Python » python条件变量Condition

python线程条件变量Condition(31)的更多相关文章
- python线程的条件变量Condition的用法实例
Condition 对象就是条件变量,它总是与某种锁相关联,可以是外部传入的锁或是系统默认创建的锁.当几个条件变量共享一个锁时,你就应该自己传入一个锁.这个锁不需要你操心,Condition 类会 ...
- Python 线程同步变量,同步条件,列队
条件变量同步 有一类线程需要满足条件之后才能够继续执行,Python提供了threading.Condition 对象用于条件变量线程的支持,它除了能提供RLock()或Lock()的方法外,还提供了 ...
- 深入解析条件变量(condition variables)
深入解析条件变量 什么是条件变量(condition variables) 引用APUE中的一句话: Condition variables are another synchronization m ...
- [development][C] 条件变量(condition variables)的应用场景是什么
产生这个问题的起因是这样的: [:] <tong> lilydjwg: 主线程要启动N个子线程, 一个局部变量作为把同样的参数传入每一个子线程. 子线程在开始的十行会处理完参数. ...
- Linux组件封装(二)中条件变量Condition的封装
条件变量主要用于实现线程之间的协作关系. pthread_cond_t常用的操作有: int pthread_cond_init(pthread_cond_t *cond, pthread_conda ...
- Linux 线程 条件变量
一:条件变量 直接上最基本的两个函数,先抓主要矛盾: //等待条件 int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex ...
- [转] 条件变量(Condition Variable)详解
http://www.wuzesheng.com/?p=1668 条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法.举个简单的例子,应用程序A ...
- 孤荷凌寒自学python第四十二天python线程控制之Condition对象
孤荷凌寒自学python第四十二天python的线程同步之Condition对象 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天学习了Condition对象,发现它综合了Event对象 ...
- 条件变量(Condition Variable)详解
条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法.举个简单的例子,应用程序A中包含两个线程t1和t2.t1需要在bool变量test_cond ...
随机推荐
- Java 异常(一)
目录 异常简介 异常架构图 常见异常 异常分类 一:异常简介 Java异常是Java提供的一种识别及响应错误的一致性机制. Java异常机制可以使程序中异常处理代码和正常业务代码分离,保证程序代码更加 ...
- Java socket Tcp协议 实现文件传输
1.文件加密上传后发现文件已损坏: 原因:使用 read(byte[]) 方法不能够准确的获取到正确的字节数,有可能比 byte[].length 小,所以在解密的时候出现错误. 解决办法: 判断读取 ...
- LeetCode 84--柱状图中最大的矩形( Largest Rectangle in Histogram) 85--最大矩形(Maximal Rectangle)
84题和85五题 基本是一样的,先说84题 84--柱状图中最大的矩形( Largest Rectangle in Histogram) 思路很简单,通过循环,分别判断第 i 个柱子能够延展的长度le ...
- Java基础(二十九)Java IO(6)对象序列化(Object Serialization)
参考之前整理过的Java序列化与反序列化:https://www.cnblogs.com/BigJunOba/p/9127414.html 使用对象输入输出流可以实现对象序列化与反序列化,可以直接存取 ...
- Mac高效开发之iTerm2、Prezto和Solarized主题
本文首发于个人网站:Mac高效开发之iTerm2.Prezto和Solarized主题 工欲善其事必先利其器,作为开发,我追求极致的高效,因此会在很多细节上追求效率,例如:命令行窗口敲命令的时候,如果 ...
- django-模板之block(四)
base.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- 阿里巴巴 Kubernetes 应用管理实践中的经验与教训
作者 | 孙健波(阿里巴巴技术专家).赵钰莹 导读:云原生时代,Kubernetes 的重要性日益凸显.然而,大多数互联网公司在 Kubernetes 上的探索并非想象中顺利,Kubernetes 自 ...
- ajax 跨域问题处理
第一种方法 服务端处理 response.addHeader("Access-Control-Allow-Origin", "*"); 第二种 客户端使用Jso ...
- MYSQL5.7修改密码强度策略
---恢复内容开始--- 在MySQL5.6.6之后,ORACLE更新了mysql密码强度必须要使用大小写数字符号来设置密码,但是有时候这样还是很不方便的.所以记录一篇如何修改mysql密码强度的博文 ...
- [BZOJ4310] 跳蚤 SAM || SA
没有代码的. 传送门 先二分出第 \(mid\) 大的字串 \(s\),然后从后往前切割,每次大于 \(s\) 了就不行. 涉及到的操作:求第 \(mid\) 大子串:比较两个字串(求 \(lcp\) ...