之前的有梳理过关于进程的python 多进程间相互协调: Event事件,这里那我们的线程其实是和进程的使用的方式大同小异的。
他们的定义和作用是保持一致的:所以这里不会展开太多关于event的一些细节。
回顾关于进程上的Event:
1 Event 方式同步通信
Event提供一种简单的方法,可以在进程间(也可以是线程间)传递状态信息,实现进程间(线程间)同步通信(不同的进程之间可以利用一些特殊的处理来等待其他进程处理完毕)
Event可以切换设置和未设置状态。通过使用一个可选的超时值,事件对象的用户可以等待其状态从未设置变为设置状态。
事件event运行的机制:
全局定义了一个Flag
如果Flag值为 False,当程序执行event.wait()方法时就会阻塞
如果Flag值为True时,程序执行event.wait()方法时不会阻塞继续执行
事件event几个方法:
wait()方法:等待是否阻塞依赖全局的Flag的值。
PS:当调用wait()方法是将进入到阻塞状态,同时会设置阻塞标记为“False”,(待阻塞标记为“True"后才会解除阻塞状态,然后继续当前进程的任务执行,wait是切换当前的状态,转移执行权)
Event 提供了如下方法:
is_set():该方法返回 Event 的内部标记是否为True。 set():该方法将会把 Event 的内部标记设置为 True,并唤醒【所有处于等待】状态的线程。
ps:当标记保持在True的状态时,线程调用wait()是不会阻塞的。
clear():该方法将 Event 的内部标记设置为 False,通常接下来会调用 wait() 方法来阻塞【当前线程】,当前线程进入阻塞,直到其他线程调用set()后来唤醒。 wait(timeout=None):该方法会阻塞【当前线程】。
ps:如果内部标志在wait()方法调用时为True,则立即返回,不会阻塞当前线程的执行。进入wait()方法通常前面是调用了clear(),再调用wait()才会启动阻塞的作用。
事件event
在的进程也是一样。上一次我们的进程中看到好像顺序是保持,一次的,其实纯属一种巧合。
进程示例如下:
#!/usr/bin/evn python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------
文件名称 : jincheng4
文件功能描述 : 功能描述
创建人 : 小钟同学
创建时间 : 2021/5/7
-------------------------------------------------
修改描述-2021/5/7:
-------------------------------------------------
全局定义了一个Flag
- 如果Flag值为 False,当程序执行event.wait()方法时就会阻塞
- 如果Flag值为True时,程序执行event.wait()方法时不会阻塞继续执行
### 事件event几个方法:
- wait()方法:等待是否阻塞依赖全局的Flag的值。
- set()方法:将Flag的值改成True
- clear()方法:将Flag的值改成False
- is_set()方法:判断当前的Flag的值
"""
import multiprocessing,time,random
def restaurant_handle(event):
print("肯德基开门了!!")
print("【服务员-1】当前事件状态:",event.is_set())
print("1、【服务员】请问你要吃点什么吗?。。。")
time.sleep(random.randint(1,3))
event.set()#解除阻塞状态
event.clear()#清除已有的状态
# 当调用wait()方法是将进入到阻塞状态,同时会设置阻塞标记为“False”,(待阻塞标记为“True"后才会接触阻塞状态)
event.wait()#等待客人点餐之后,才能进行下一步的后续处理
print("3、【服务员】你自己一个人这么能吃啊!。。。")
time.sleep(random.randint(1,3))
event.set() #解除阻塞状态
event.clear() # 之前的状态清空
event.wait()
print("5、【服务员】好的,我现在就给你下单,请你稍等。。。")
time.sleep(random.randint(1,3))
event.set() # 解除阻塞状态
event.clear() # 之前的状态清空
event.wait()
print("7、【服务员】好的,你稍等一下~~~。。。")
time.sleep(random.randint(1,3))
event.set()
# event.clear()
# event.wait()
print("8、【服务员】客人你点的:一个鸡腿+一个汉堡+一个这么大的鸡排 已做好了!请慢慢享用!")
time.sleep(random.randint(1,3))
# event.set()
# event.clear()
event.wait()
print("11、【服务员】好的,总共消费1000快!。。。")
time.sleep(random.randint(1, 3))
event.set() # 解除阻塞状态
event.clear() # 之前的状态清空
event.wait()
def diners_hangle(event):#食客的处理进程
print("当前事件状态:", event.is_set())
event.wait() #等待之前的第一步完成 两个进程所以先阻塞,让另一个执行
print("2、【客人】我要点一个鸡腿+一个汉堡+一个这么大的鸡排!。。。")
time.sleep(random.randint(1,3))
event.set() #解除阻塞状态
event.clear()#之前的状态清空
event.wait()#继续等待后续的处理步骤
print("4、【客人】怎么不可以吗?快下单吧~我都饿的叽里咕噜了~")
time.sleep(random.randint(1,3))
event.set()
event.clear()
event.wait()
print("6、【客人】让师傅做快一点。。。")
time.sleep(random.randint(1,3))
event.set()
event.clear()
event.wait()
print("9、【客人】好的,我开始吃了~~~~")
# event.set()
time.sleep(random.randint(1, 3))
print("10、【客人】吃完了!服务员,我买单!!!~~~~")
time.sleep(random.randint(1, 3))
event.set()
event.clear()
event.wait()
print("12、【客人】这么黑~~1000快!!不给!!我跑了!再见!~~~~")
event.set()
def main():
# 定义一个event同步处理,默认是处于阻塞的状态
event = multiprocessing.Event()
restaurant_process = multiprocessing.Process(target=restaurant_handle,args=(event,),name="肯德基服务进程")
diners_process = multiprocessing.Process(target=diners_hangle,args=(event,),name="客人进程")
restaurant_process.start()
diners_process.start()
if __name__ == '__main__':
main()
输出结果为:
D:\ceshi>python jincheng5.py
肯德基开门了!!
【服务员-1】当前事件状态:False
1、【服务员】请问你要吃点什么吗?。。。
当前事件状态:False
2、【客人】我要点一个鸡腿+一个汉堡+一个这么大的鸡排!。。。
3、【服务员】你自己一个人这么能吃啊!。。。
4、【客人】怎么不可以吗?快下单吧~我都饿的叽里咕噜了~
5、【服务员】好的,我现在就给你下单,请你稍等。。。
6、【客人】让师傅做快一点。。。
7、【服务员】好的,你稍等一下~~~。。。
8、【服务员】客人你点的:一个鸡腿+一个汉堡+一个这么大的鸡排 已做好了!请慢慢享用!
9、【客人】好的,我开始吃了~~~~
10、【客人】吃完了!服务员,我买单!!!~~~~
11、【服务员】好的,总共消费1000快!。。。
12、【客人】这么黑~~1000快!!不给!!我跑了!再见!~~~~
PS:上面的输出就结果看着是按顺序,但是其实再某种情况是不会按顺序执行,!
修改为线程形式:
#!/usr/bin/evn python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------
-------------------------------------------------
"""
import multiprocessing,time,random
import threading
# 创建event事件
event = threading.Event()
def restaurant_handle(event):
print("肯德基开门了!!")
print("【服务员-1】当前事件状态:",event.is_set())
print("1、【服务员】请问你要吃点什么吗?。。。")
time.sleep(random.randint(1,3))
event.set()#解除阻塞状态
event.clear()#清除已有的状态
# 当调用wait()方法是将进入到阻塞状态,同时会设置阻塞标记为“False”,(待阻塞标记为“True"后才会接触阻塞状态)
event.wait()#等待客人点餐之后,才能进行下一步的后续处理
print("3、【服务员】你自己一个人这么能吃啊!。。。")
time.sleep(random.randint(1,3))
event.set() #解除阻塞状态
event.clear() # 之前的状态清空
event.wait()
print("5、【服务员】好的,我现在就给你下单,请你稍等。。。")
time.sleep(random.randint(1,3))
event.set() # 解除阻塞状态
event.clear() # 之前的状态清空
event.wait()
print("7、【服务员】好的,你稍等一下~~~。。。")
time.sleep(random.randint(1,3))
event.set()
# event.clear()
# event.wait()
print("8、【服务员】客人你点的:一个鸡腿+一个汉堡+一个这么大的鸡排 已做好了!请慢慢享用!")
time.sleep(random.randint(1,3))
# event.set()
# event.clear()
event.wait()
print("11、【服务员】好的,总共消费1000快!。。。")
time.sleep(random.randint(1, 3))
event.set() # 解除阻塞状态
event.clear() # 之前的状态清空
event.wait()
def diners_hangle(event):#食客的处理进程
print("当前事件状态:", event.is_set())
event.wait() #等待之前的第一步完成 两个进程所以先阻塞,让另一个执行
print("2、【客人】我要点一个鸡腿+一个汉堡+一个这么大的鸡排!。。。")
time.sleep(random.randint(1,3))
event.set() #解除阻塞状态
event.clear()#之前的状态清空
event.wait()#继续等待后续的处理步骤
print("4、【客人】怎么不可以吗?快下单吧~我都饿的叽里咕噜了~")
time.sleep(random.randint(1,3))
event.set()
event.clear()
event.wait()
print("6、【客人】让师傅做快一点。。。")
time.sleep(random.randint(1,3))
event.set()
event.clear()
event.wait()
print("9、【客人】好的,我开始吃了~~~~")
# event.set()
time.sleep(random.randint(1, 3))
print("10、【客人】吃完了!服务员,我买单!!!~~~~")
time.sleep(random.randint(1, 3))
event.set()
event.clear()
event.wait()
print("12、【客人】这么黑~~1000快!!不给!!我跑了!再见!~~~~")
event.set()
def main():
# event = multiprocessing.Event()
# restaurant_process = multiprocessing.Process(target=restaurant_handle,args=(event,),name="肯德基服务进程")
# 创建并初始化线程
restaurant_thread = threading.Thread(target=restaurant_handle, args=(event,), name="肯德基服务进程", )
diners_thread = threading.Thread(target=diners_hangle, args=(event,), name="客人进程", )
# diners_process = multiprocessing.Process(target=diners_hangle,args=(event,),name="客人进程")
# restaurant_process.start()
# 全局内置标志Flag,将标志Flag 设置为 True,通知在等待状态(wait)的线程恢复运行;
# 启动线程
restaurant_thread.start()
diners_thread.start()
restaurant_thread.join()
diners_thread.join()
if __name__ == '__main__':
main()
输出结果为:
肯德基开门了!!
【服务员-1】当前事件状态:False
1、【服务员】请问你要吃点什么吗?。。。
当前事件状态:False
2、【客人】我要点一个鸡腿+一个汉堡+一个这么大的鸡排!。。。
3、【服务员】你自己一个人这么能吃啊!。。。
4、【客人】怎么不可以吗?快下单吧~我都饿的叽里咕噜了~
5、【服务员】好的,我现在就给你下单,请你稍等。。。
6、【客人】让师傅做快一点。。。
7、【服务员】好的,你稍等一下~~~。。。
8、【服务员】客人你点的:一个鸡腿+一个汉堡+一个这么大的鸡排 已做好了!请慢慢享用!9、【客人】好的,我开始吃了~~~~
11、【服务员】好的,总共消费1000快!。。。
10、【客人】吃完了!服务员,我买单!!!~~~~
后面输出执行的时候,看到是不一样的顺序!所以这个地方说明了有可能当event.set()的时候,当前线程又抢回执行权了!所以导致顺序乱了!
个人其他博客地址
简书:https://www.jianshu.com/u/d6960089b087
掘金:https://juejin.cn/user/2963939079225608
小钟同学 | 文 【原创】| QQ:308711822
1:本文相关描述主要是个人的认知和见解,如有不当之处,还望各位大佬指正。 2:关于文章内容,有部分内容参考自互联网整理,如有链接会声明标注;如没有及时标注备注的链接的,如有侵权请联系,我会立即删除处理哟。




