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 ...
随机推荐
- 使用JRebel插件实现SpringBoot应用代码热加载
前言 在实际的开发过程中,我们经常修改代码之后,手动的重启项目,查看修改效果.那么有没有一种方式能够快速的.自动的帮我们将修改代码自动更新,避免手动重启,从而提高开发效率呢?是有的,在我之前的文章里面 ...
- 基于 HTML5 + Canvas 实现楼宇自控系统
前言 楼宇自控是指楼宇中电力设备,如电梯.水泵.风机.空调等,其主要工作性质是强电驱动.通常这些设备是开放性的工作状态,也就是说没有形成一个闭环回路.只要接通电源,设备就在工作,至于工作状态.进程.能 ...
- JVM(3) 垃圾收集器与内存分配策略
一.垃圾收集的概念 在Java虚拟机运行时数据区中程序计数器.虚拟机栈和本地方法栈3个区域随线程而生,随线程而灭:栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作,每一个栈帧中分配多少内 ...
- R语言之脸谱图
脸谱图和星图类似,但它却比星图可以表示更多的数据维度.用脸谱来分析多维度数据,即将P个维度的数据用人脸部位的形状或大小来表征.脸谱图在平面上能够形象的表示多维度数据并给人以直观的印象,可帮助使用者形象 ...
- (Java) JWT-TokenUtils
package com.vcgeek.hephaestus.utils; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; imp ...
- linux 编译引用动态库时,报GLIBC_2,14 not found的处理方法
这种错误一般是其引用的libc.so,其中含有版本较高的函数导致. 查看及解决办法: objdump -p ./libdmapi.so 显示: version References: ... requ ...
- CVE-2019-16097:Harbor任意管理员注册漏洞复现
0x00 Harbor简介 Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,通过添加一些企业必需的功能特性,例如安全.标识和管理等,扩展了开源Docker Distri ...
- 题解【洛谷】CF134A
题解 CF134A [Average Numbers] 这题就是简单的模拟. 只不过要优化一下常数什么的 思路: 为了不浪费时间总是取平均数,直接用一个 S 储存总和,每次都减去 a_i 再除以 n ...
- 区块链之Hyperledger(超级账本)Fabric v1.0 的环境搭建(超详细教程)
https://blog.csdn.net/so5418418/article/details/78355868
- git上传项目到github远程库
最近在学习使用 git 上传管理项目,依照教程,建好了一个远程库,也实现了本地库与远程库的项目同步上传,但是在试着将本地库里的项目上传到另一个新建远程库时遇到了问题,一直上传不成功,经过一番查找摸索终 ...