对于线程与线程之间的交互我们在前面的文章已经介绍了 python 互斥锁Lock / python事件Event , 今天继续介绍一种线程交互方式 – 线程条件变量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的作用就是通知所有线程;
在前面的文章已经介绍过互斥锁,主要作用是并行访问共享资源时,保护共享资源,防止出现脏数据。python 条件变量Condition也需要关联互斥锁,同时Condition自身提供了wait/notify/notifyAll方法,用于阻塞/通知其他并行线程,可以访问共享资源了。可以这么理解,Condition提供了一种多线程通信机制,假如线程1需要数据,那么线程1就阻塞等待,这时线程2就去制造数据,线程2制造好数据后,通知线程1可以去取数据了,然后线程1去获取数据。
案例一:成语接龙
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | # !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("程序结束!") |
输出结果:
1 2 3 4 5 6 7 8 | A:成语接龙准备好了吗 B:准备好了~开始吧! A:一干二净 B:净你妹啊,没法接...来个简单点的... A:一天就知道看抖音美女,给你来个简单点的,来了:毛手毛脚 B:嘿,这个我知道:脚踏实地 A:哟哟哟,不错不错! 程序结束! |
案例二:生产者与消费者模式,以吃火锅为例:一盘老肉片有10块肉,吃完了又重新往锅里加….
生产者:往锅里加老肉片,每次加一盘(10块);
消费者:吃煮熟的肉片,没吃一片,肉片数量减一,吃完为止;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | # 导入线程模块 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("程序结束!") |
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 肉片熟了,可以开始吃了... 我来一块肉片... 剩余肉片数量: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
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。