python学习Day36--信号 事件

一、回顾

1、一些名词回顾:

并行:两个进程在同一时间点发生

并发:两个进程在同一时间间隔内运行

同步:某一个任务的执行必须依赖于另一个任务的返回结果

异步:某一个任务的执行,不需要依赖于另一个任务的返回,只需要告诉另一个任务一声

阻塞:程序因为类似IO等待,等待事件导致无法继续执行

非阻塞:程序遇到类似IO操作时,不再阻塞等待,如果没有及时的处理IO,就报错或者跳过等替他操作

2、进程的方法和属性:

(1)方法:

  start( )    开启一个进程

  join( )      异步变同步,让父进程等待子进程的结束,再继续执行

  is_alive( )    判断进程是否活着

  terminate     杀死进程

(2)属性:

  name    子进程的名称

  pid         子进程的pid

  daemon            设置进程为守护进程,给一个True代表为守护进程,默认为False

3、守护进程:

(1)特点:

  随着父进程的结束而结束

  守护进程不能创建子进程

  守护进程必须要在start之前设置

(2)代码:

 1 from multiprocessing import Process
 2 
 3 import time
 4 
 5 def func1():
 6     for i in range(65,90):
 7         print(chr(i))
 8         time.sleep(0.5)
 9 
10 def func():
11     for i in range(10):
12         print(i)
13         time.sleep(0.5)
14 
15 if __name__ == '__main__':
16     p = Process(target=func)
17     p.start()
18     p1 = Process(target=func1)
19     p1.daemon = True
20     p1.start()
21     # time.sleep(2)
22 
23     # print(p.is_alive())
24     # p.terminate()
25     # p.join()
26     # print(p.is_alive())
27     # print(p.pid,p.name)
28     # for i in range(10,21):
29     #     print(i)
30     #     time.sleep(1)

二、锁机制

1、问题的产生?

  数据共享使用时可能会出现混乱,比如以下代码实现的数据共享就会出现这样的情况。

 1 # *******************问题**********************开始
 2 from multiprocessing import Process,Value
 3 import time
 4 
 5 def get_money(num): # 取钱
 6     for i in range(100):
 7         num.value -= 1
 8         time.sleep(0.01)
 9 
10 def put_money(num): # 存钱
11     for i in range(100):
12         num.value += 1
13         time.sleep(0.01)
14 
15 if __name__ == '__main__':
16     num = Value('i',100) # 数据类型+值(数据共享)
17     p = Process(target=get_money,args=(num,))
18     p.start()
19     p1 = Process(target=put_money,args=(num,))
20     p1.start()
21     p.join()
22     p1.join()
23     print(num.value) # 获取到子进程的num
24 # *******************问题**********************结束
问题

2、解决问题——锁机制

(1)锁涉及两个操作:

  拿钥匙,锁门:——不让别人进屋

  换钥匙,开门:——让别人进屋

(2)锁的特点是:一把钥匙配一把锁

(3)锁的相关代码:

1 from multiprocessing import Lock
2 
3 l = Lock()
4 
5 l.acquire()  # 拿走钥匙,锁门,不让其他人进屋
6 
7 l.release()  # 释放锁,还钥匙,开门,允许其他人进入

(4)用锁解决问题对应的代码

 1 from multiprocessing import Process,Value,Lock
 2 import time
 3 
 4 def get_money(num,l): # 取钱
 5     l.acquire() # 拿走钥匙,锁上门,不让其他人进来
 6     for i in range(100):
 7         num.value -= 1
 8         time.sleep(0.01)
 9     l.release()  # 还钥匙,开门,允许其他人进入
10 
11 def put_money(num,l): # 存钱
12     l.acquire()  # 拿走钥匙,锁上门,不让其他人进来
13     for i in range(100):
14         num.value += 1
15         time.sleep(0.01)
16     l.release()  # 还钥匙,开门,允许其他人进入
17 
18 if __name__ == '__main__':
19     l = Lock()  # 设置一把锁
20     num = Value('i',100) # 数据类型+值(数据共享)
21     p = Process(target=get_money,args=(num,l))
22     p.start()
23     p1 = Process(target=put_money,args=(num,l))
24     p1.start()
25     p.join()
26     p1.join()
27     print(num.value) # 获取到子进程的num

(5)模拟抢票

 1 # *******************抢票**********************开始
 2 from multiprocessing import Process,Lock
 3 import time
 4 
 5 
 6 def check(i):
 7     with open("余票") as f:
 8         con = f.read()
 9     print("第%s个人查到余票还剩%s张" % (i,con))
10 
11 def buy_ticket(i,l):
12     # 这里的锁是保护在多进程中数据安全
13     l.acquire()
14     with open("余票") as f:
15         con = int(f.read())
16         time.sleep(0.1)
17 
18     if con > 0:
19         print('\033[31m 第%s个人买到了票\033[0m' % i)
20         con -= 1
21     else:
22         print("\033[32m 第%s个人没有买到票\033[0m" % i)
23     time.sleep(0.1) # 是指,买完票后,把余票数量重新写入数据库的延迟时间
24 
25     with open("余票",'w') as f:
26         f.write(str(con))
27     l.release()
28 
29 
30 if __name__ == '__main__':
31     l = Lock()
32     for i in range(10):
33         p_ch = Process(target=check,args=(i+1,))
34         p_ch.start()
35     for i in range(10):
36         p_buy = Process(target=buy_ticket,args=(i+1,l))
37         p_buy.start()
38 
39 # *******************抢票**********************结束
模拟抢票

三、信号机制

1、信号量

  一把锁配多把钥匙。、

  信号量机制比锁机制多了一个计数器,这个计数器是用来记录当前剩余几把钥匙的。

 1 from multiprocessing import Semaphore
 2 
 3 l = Semaphore(3)  # 一把锁配3把钥匙
 4 
 5 l.acquire() # 拿走一把钥匙,锁上门
 6 print(123)
 7 l.acquire() # 拿走一把钥匙,锁上门
 8 print(456)
 9 l.acquire() # 拿走一把钥匙,锁上门
10 print(789)
11 l.acquire() # 在此会阻塞,等待其他钥匙归还(释放)
12 print(111)

2、举例操作

 1 # *******************信号机制——案例**********************开始
 2 from multiprocessing import Semaphore,Process
 3 import time
 4 import random
 5 
 6 def func(i,sem):
 7     sem.acquire()
 8     print('第%s个人进入小黑屋,拿了钥匙上门' % i)
 9     time.sleep(random.randint(3,5))
10     print('第%s个人出去小黑屋,还了钥匙打开门' % i)
11     sem.release()
12 
13 if __name__ == '__main__':
14     sem = Semaphore(5) # 初始化一把锁5把钥匙
15     for i in range(20):
16         p = Process(target=func,args=(i,sem,))
17         p.start()
18 # *******************信号机制——案例**********************结束

四、事件机制

1、事件机制介绍: 

  事件是通过is_set( )的bool值,去标识e.wait( )的阻塞状态。

  当is_set( )的bool值为False时,e.wait( )是阻塞状态。

  当is_set( )的bool值为True时,e.wait( )是非阻塞状态。

  当使用set( )时,是把is_set的bool值变为True.

  当使用clear( )时,是把is_set的bool值变为False。

 1 from multiprocessing import Event
 2 
 3 e = Event()
 4 
 5 print(e.is_set()) # False
 6 e.set() # 将is_set的bool值变为True, 将wait变为非阻塞
 7 e.wait()
 8 print(e.is_set()) # True
 9 print(123)
10 e.clear()
11 print(e.is_set()) # False
12 e.wait()  # 阻塞
13 print(456)

2、案例:

  红绿灯事件。

 1 # *******************事件机制——案例**********************开始
 2 from multiprocessing import Process,Event
 3 import time
 4 
 5 
 6 def tra(e):
 7     '''信号灯函数'''
 8     e.set()
 9     print("\033[32m 绿灯亮! \033[0m")  # 红灯亮了5秒后提示绿灯亮
10     while 1:
11         if e.is_set(): # True,代表绿灯亮,那么此时代表可以过车
12             time.sleep(5) # 所以在这让灯等5秒钟,这段时间让车过
13             print('\033[31m 红灯亮! \033[0m') # 绿灯亮了5秒应该提示红灯亮
14             e.clear() # 把is_set设置为False
15         else:
16             time.sleep(5) # 此时代表红灯亮了,红灯亮5秒
17             print("\033[32m 绿灯亮! \033[0m") # 红灯亮了5秒后提示绿灯亮
18             e.set() # 将is_set设置为True
19 
20 
21 def Car(i,e):
22     e.wait() # 车在等红绿灯,is_set为False时不过,True时过车
23     print("第%s辆车过去了" % i)
24 
25 if __name__ == '__main__':
26     e = Event()
27     traffic_light = Process(target=tra,args=(e,)) # 信号灯的进程
28     traffic_light.start()
29     for i in range(50): # 描述50辆车
30         if i % 3 == 0:
31             time.sleep(2)
32         car = Process(target=Car,args=(i+1,e,)) # 汽车的进程
33         car.start()
34 # *******************事件机制——案例**********************结束

 

posted @ 2020-04-17 01:13  红叶楠木  阅读(231)  评论(0编辑  收藏  举报