python 线程超时设置_python 条件变量Condition(36)

文章首发微信公众号,微信搜索:猿说python

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

v2-6433c48aa4434a8c67ba914696eed481_b.jpg

一.线程条件变量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的作用就是通知所有线程;

v2-9f7eae5408bfcdfdde997c78d17774e4_b.jpg

二.线程条件变量Condition原理

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

v2-ae5bbf94118ba6e2b3b6d26691c49d23_b.jpg

三.线程条件变量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:哟哟哟,不错不错!
程序结束!

v2-a43bd4d06d5e52fe254a5240f3cdfba1_b.jpg

案例二:生产者与消费者模式,以吃火锅为例:一盘老肉片有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可以用于比较复杂的线程交互!

猜你喜欢:

1.python线程创建和参数传递

2.python线程互斥锁Lock

3.python线程事件Event

4.python return逻辑判断表达式

转载请注明:猿说Python » python条件变量Condition

想了解更多python内容请直接搜索微信公众号:猿说python

Python教程 - 猿说Python​www.shuopython.com
v2-94ebac7f53f66e16a00e0604e0f4e3ce_180x120.jpg

本人也还在学习python中,博客会持续更新ing,有兴趣的小伙伴关注走一波,推荐浏览个人博客网站:猿说python,文章采用树状分类,结构目录清晰一点,文章内容有问题的话欢迎给出建议或者直接留言.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值