• 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('33[31m 第%s个人买到了票33[0m' % i)
    20         con -= 1
    21     else:
    22         print("33[32m 第%s个人没有买到票33[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("33[32m 绿灯亮! 33[0m")  # 红灯亮了5秒后提示绿灯亮
    10     while 1:
    11         if e.is_set(): # True,代表绿灯亮,那么此时代表可以过车
    12             time.sleep(5) # 所以在这让灯等5秒钟,这段时间让车过
    13             print('33[31m 红灯亮! 33[0m') # 绿灯亮了5秒应该提示红灯亮
    14             e.clear() # 把is_set设置为False
    15         else:
    16             time.sleep(5) # 此时代表红灯亮了,红灯亮5秒
    17             print("33[32m 绿灯亮! 33[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 # *******************事件机制——案例**********************结束
  • 相关阅读:
    poj 1679 The Unique MST(次小生成树)
    利用微软翻译API做自己的翻译的工具(java)
    第一次用hql语句显示:QuerySyntaxException
    解决java用url中读取html源码时的乱码问题
    用java写的TrieTree
    OpenSessionInViewFilter失效问题
    windows下hadoop伪分布式模式开发环境的搭建(Cygwin)以及Eclipse集成开发环境下的搭建
    毕业设计想做一个垂直搜索引擎,关于手机方面
    struts2自定义拦截器
    根据地区和时区获取当地时间
  • 原文地址:https://www.cnblogs.com/fengxb1213/p/12717107.html
Copyright © 2020-2023  润新知