python学习笔记 day36 事件

1. Event事件 ---标志,可以实现异步阻塞

之前input,recv,accpet sleep等都是同步阻塞(写在哪个进程就会阻塞哪个),然后学了Lock锁 和信号量Semophore 都可以实现异步阻塞,同时阻塞多个进程(比如锁 只是同一时间只允许一个进程执行任务,所以比如开10个进程,就会同时异步阻塞九个)然后Semophore信号量可以允许多把钥匙,同一时间多个进程拿到钥匙执行任务,就会异步阻塞其他的进程(只能等着)

现在Event 事件可以完成同时阻塞所有进程(相当于是一个标志,可以理解为交通信号灯,然后开的进程理解为车。交通信号灯,event为红(阻塞)进程,车就不能通过表现为阻塞,event 或交通灯为绿,车进程就可以通过,表现为非阻塞)

 

from multiprocessing import Event
e=Event()  # 实例化一个事件,默认阻塞(可以理解为交通信号灯,一开始红灯)
e.set()  # 设置为非阻塞(交通灯变绿)
e.wait()   # 默认为阻塞(红灯),set()之后变为非阻塞,(变绿)
e.clear()   # 设置为阻塞(红灯),刚才的绿灯现在变为i红灯
# e.wait()  # clear之后现在wait()就会一直阻塞

运行结果:

 

2. 使用事件模拟交通路口车辆通过:

思路:

首先实现一个traffic_light()函数,主要是完成交通灯红绿灯转换(三秒轮换),设置事件e的状态 阻塞和非阻塞每三秒转换;
实现car() 完成车辆通过,会用到e的状态,阻塞,非阻塞,非阻塞时wait()直接就不等待,直接执行下面的代码,阻塞时就会一直等待,直到事件e变为非阻塞状态;

在主进程中先开一个子进程,来执行交通灯转换,(由于是死循环,所以需要开一个子进程来完成,否则主进程会一直阻塞,无法执行下面的代码)

然后开100个进程,模拟车,可以利用random模块和time模块设置并发,随机来多少辆车(根据i决定是否来,同时来的车辆i就是并发),然后执行car函数,是否立马通过,取决于e事件的是否阻塞状态,也就是是否为绿灯:

代码实现:

 

from multiprocessing import Process
from multiprocessing import Event
import random
import time

def traffic_light(e):
    """
    模拟交通灯,实际上是设置事件的阻塞状态,每三秒转换一次,代表红绿灯的转换
    :param e:
    :return:
    """
    while True:  # 死循环,红绿灯转换是需要一直工作的,事件e的阻塞状态一直在变(所以该函数需要单独要开一个子进程来实现,否则主进程会一直执行该死循环)
        if e.is_set():  # 查看事件e的阻塞状态,True代表非阻塞(绿灯)
            print("绿灯亮")
            time.sleep(3)  # 绿灯亮三秒
            e.clear()  # 设置为阻塞状态
        else:
            print("红灯亮")
            time.sleep(3)
            e.set()  # 红灯亮三秒后设置为绿灯(非阻塞)
def car(i,e):
    """
    模拟车辆通过,车辆是否立马通过,取决于红绿灯的状态,也就是进程是否阻塞,取决于事件e的阻塞状态
    :param i:
    :param e:
    :return:
    """
    e.wait()   # 事件e阻塞时,这里会一直等待,直到事件set()也就是设置为非阻塞,才会执行下面的代码,不再等待
    print("%s车辆通过"%i)

if __name__=="__main__":
    e=Event() # 实例化一个事件
    p=Process(target=traffic_light,args=(e,))   # 单独开一个子进程执行traffic_light()函数,因为该函数是个死循环,绝对不能在主进程中完成的
    p.start()
    for i in range(100):   # 创建100个进程(模拟100辆车)
        if i%random.randint(3,7)==0:  # 随机产生并发车辆的数目(有可能同时来3辆,有可能同时来5辆,都不确定)
            time.sleep(random.randint(1,3))  # 随机睡几秒(比如如果i是5 上面的随机数产生的刚好也是5 那么这个车辆就不会立马来,会先睡几秒,不会是并发的车辆)
        p=Process(target=car,args=(i,e))  # 并发的车辆(就是没有睡的)开启进程,但是是否立即通过取决于此时事件是否阻塞,如果阻塞就会等三秒,变为非阻塞,并发车辆才会同时通过
        p.start()

运行结果:

运行结果也是对的,,直观上好像红灯亮的时候车辆也过,但是(红灯亮的时候是不会立马有车辆通过,会等三秒才会有车辆通过的~) 

 

或者直接把traffic_light()改成:

 

运行结果:

 

posted @ 2018-10-12 11:30  写的BUG代码少  阅读(196)  评论(0编辑  收藏  举报