扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
对于线程与线程之间的交互我们在前面的文章已经介绍了 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:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累! """ # 导入线程模块 importthreading # 创建条件变量condition con=threading.Condition() defthread_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() defthread_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 | # 导入线程模块 importthreading importtime # 创建条件变量condition con=threading.Condition() meat_num=0 defthread_consumers(): # 条件变量condition 线程上锁 con.acquire() # 全局变量声明关键字 global globalmeat_num meat_num=0 # 等待肉片下锅煮熟 con.wait() whileTrue: print("我来一块肉片...") meat_num-=1 print("剩余肉片数量:%d"%meat_num) time.sleep(0.5) ifmeat_num==0: # 肉片吃光了,通知老板添加肉片 print("老板,再来一份老肉片...") con.notify() # 肉片吃光了,等待肉片 con.wait() # 条件变量condition 线程释放锁 con.release() defthread_producer(): # 条件变量condition 线程上锁 con.acquire() # 全局变量声明关键字 global globalmeat_num # 肉片熟了,可以开始吃了 meat_num=10 print("肉片熟了,可以开始吃了...") con.notify() whileTrue: # 阻塞函数,等待肉片吃完的通知 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
另外有需要云服务器可以了解下创新互联cdcxhl.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流