• 041.Python守护进程,锁信号量和事件



    一 守护进程

    1.1 基本概念

    守护进程

    • 正常情况下,主进程默认等待子进程调用结束之后结束
    • 守护进程在主进程执行代码结束后,自动终止

    守护进程语法:

    • 进程对象.daemon = True ,设置该进程是守护进程
    • 守护进程需要在start()方法之前设置
    • 为主进程守护,主进程如果代码执行结束了,该守护进程自动结束.

    1.2 基本语法

    复制代码
    import os
    import time
    from multiprocessing import Process
    def func():
            print("子进程start")
            print("子进程end")
    p = Process(target=func)
    p.start()
    print ("主进程执行结束")
    复制代码

    执行

    [root@node10 python]# python3 test.py
    主进程执行结束
    子进程start
    子进程end

    使用守护进程

    复制代码
    import os
    import time
    from multiprocessing import Process
    def func():
            print("子进程start")
            print("子进程end")
    p = Process(target=func)
    p.daemon = True
    p.start()
    print ("主进程执行结束")
    复制代码

    执行

    [root@node10 python]# python3 test.py
    主进程执行结束

    主进程执行完之后,子进程不在执行

    1.3 多个子进程情况

    复制代码
    import os
    import time
    from multiprocessing import Process
    def func1():
            count = 1
            while True:
                    print ("*" * count)
                    time.sleep(0.5)
                    count += 1
    def func2():
            print("func2 start")
            time.sleep(3)
            print("func2 end")
    p1 = Process(target=func1)
    p1.start()
    p2 = Process(target=func2)
    p2.start()
    print ("主进程执行结束")
    复制代码

    执行

    复制代码
    [root@node10 python]# python3 test.py
    主进程执行结束
    *
    func2 start
    **
    ***
    ****
    *****
    ******
    func2 end
    *******
    ********
    *********
    **********
    ***********
    ************
    *************
    **************
    ***************
    ****************
    *****************
    ******************
    *******************
    ********************
    *********************
    **********************
    复制代码

    第一个进程不能结束,设置一个守护进程

    复制代码
    import os
    import time
    from multiprocessing import Process
    def func1():
            count = 1
            while True:
                    print ("*" * count)
                    time.sleep(0.5)
                    count += 1
    def func2():
            print("func2 start")
            time.sleep(3)
            print("func2 end")
    p1 = Process(target=func1)
    p1.daemon = True
    p1.start()
    p2 = Process(target=func2)
    p2.start()
    print ("主进程执行结束")
    复制代码

    但这种添加还没来得及执行,就被杀掉

    执行

    [root@node10 python]# python3 test.py
    主进程执行结束
    func2 start
    func2 end

    当多个子进程并发执行时,默认主进程等待子进程的

    如果标记该子进程是守护进程,当主进程执行完所有代码之后,守护进程立刻终止

    主进程代码执行到最后一行,就意味着守护进程终止了,其他非守护进程继续执行,主进程仍然会等待他执行结束,最后主进程在真正的释放结束.

    1.4 守护进程用途: 报活功能

    复制代码
    import os
    import time
    from multiprocessing import Process
    def alive():
            while True:
                    print ("I am the first server,I'm  OK")
                    time.sleep(0.5)
    def func():
            print("The first server is used to collect logs")
            time.sleep(5)   #相当于这个进程存活5s
    p1 = Process(target=alive)
    p1.daemon = True
    p1.start()
    p2 = Process(target=func)
    p2.start()
    #模拟func程序结束,或者服务器宕机,停止保活,这是执行主进程,执行完,则子进程不在执行,即停止报活
    p2.join()
    print (".......")
    复制代码

    执行

    复制代码
    [root@node10 python]# python3 test.py
    I am the first server,I'm  OK
    The first server is used to collect logs
    I am the first server,I'm  OK
    I am the first server,I'm  OK
    I am the first server,I'm  OK
    I am the first server,I'm  OK
    I am the first server,I'm  OK
    I am the first server,I'm  OK
    I am the first server,I'm  OK
    I am the first server,I'm  OK
    I am the first server,I'm  OK
    .......
    复制代码

    二 lock锁

    复制代码
    语法:
    # 创建一把锁
    lock = lock()
    # 上锁
    lock.acquire()
    # 解锁
    lock.release()
    复制代码

    2.1 基本用法

    复制代码
    import os
    import time
    from multiprocessing import Process,Lock
    lock = Lock()
    lock.acquire()
    lock.release()
    print (111)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    111

    死锁 上锁和解锁之间不匹配,只上锁不解锁就是死锁,会产生阻塞;

    复制代码
    import os
    import time
    from multiprocessing import Process,Lock
    lock = Lock()
    lock.acquire()
    #lock.release()
    print (111)
    复制代码

    执行就会被阻塞,而且不会打印111,成了一把死锁

    2.2 模拟一个抢票机制

    假设只有一张票

    [root@node10 python]# vim ticket

    {"count": 1}

    抢票方法

    复制代码
    import os
    import time,json
    from multiprocessing import Process,Lock
    def wr_info(sign,dic=None):
            if sign == "r":
                    with open("ticket",mode="r",encoding="utf-8") as fp:
                            dic = json.load(fp)
                    return dic
            elif sign == "w":
                    with open("ticket",mode="w",encoding="utf-8") as fp:
                            json.dump(dic,fp)
    
    #抢票方法
    def get_ticket(person):
            dic = wr_info("r")
            time.sleep(0.11)
            if dic["count"] > 0:
                    print("%s抢到票"%(person))
                    dic["count"] -=1
    #               更新数据库
                    wr_info("w",dic)
            else:
                    print ("%s没有买到票"%(person))
    
    
    #用ticket来仅从统一调用
    def ticket(person):
            #查询票数
            dic = wr_info("r")
            print ("%s查询余票:%s"%(person,dic['count']))
            get_ticket(person)
    
    for i in range(10):
            p = Process(target = ticket,args=( "person%s" %(i), ))
            p.start()
    复制代码

    执行

    复制代码
    [root@node10 python]# python3 test.py
    person0查询余票:1
    person1查询余票:1
    person2查询余票:1
    person3查询余票:1
    person4查询余票:1
    person5查询余票:1
    person6查询余票:1
    person7查询余票:1
    person8查询余票:1
    person9查询余票:1
    person3抢到票
    person0抢到票
    person4抢到票
    person5抢到票
    person1抢到票
    person7抢到票
    person2抢到票
    person6抢到票
    person8抢到票
    person9抢到票
    复制代码

    发现所有人都抢到票了

    2.3 使用锁机制

    在主进程创建一把锁,在抢票处上锁,然后再抢完解锁,如下操作

    复制代码
    import os
    import time,json
    from multiprocessing import Process,Lock
    def wr_info(sign,dic=None):
            if sign == "r":
                    with open("ticket",mode="r",encoding="utf-8") as fp:
                            dic = json.load(fp)
                    return dic
            elif sign == "w":
                    with open("ticket",mode="w",encoding="utf-8") as fp:
                            json.dump(dic,fp)
    
    #抢票方法
    def get_ticket(person):
            dic = wr_info("r")
            time.sleep(0.11)
            if dic["count"] > 0:
                    print("%s抢到票"%(person))
                    dic["count"] -=1
    #               更新数据库
                    wr_info("w",dic)
            else:
                    print ("%s没有买到票"%(person))
    
    
    #用ticket来仅从统一调用
    #这里需要把lock传进来
    def ticket(person,lock):
            #查询票数
            dic = wr_info("r")
            print ("%s查询余票:%s"%(person,dic['count']))
            lock.acquire()
            get_ticket(person)
            lock.release()
    lock = Lock()
    for i in range(10):
            p = Process(target = ticket,args=( "person%s" %(i), ))
            p.start()
    复制代码

    执行

    主进程在执行ticket的子进程时,多一个参数

    复制代码
    import os
    import time,json
    from multiprocessing import Process,Lock
    def wr_info(sign,dic=None):
            if sign == "r":
                    with open("ticket",mode="r",encoding="utf-8") as fp:
                            dic = json.load(fp)
                    return dic
            elif sign == "w":
                    with open("ticket",mode="w",encoding="utf-8") as fp:
                            json.dump(dic,fp)
    
    #抢票方法
    def get_ticket(person):
            dic = wr_info("r")
            time.sleep(0.11)
            if dic["count"] > 0:
                    print("%s抢到票"%(person))
                    dic["count"] -=1
    #               更新数据库
                    wr_info("w",dic)
            else:
                    print ("%s没有买到票"%(person))
    
    
    #用ticket来仅从统一调用
    #这里需要把lock传进来
    def ticket(person,lock):
            #查询票数
            dic = wr_info("r")
            print ("%s查询余票:%s"%(person,dic['count']))
            lock.acquire()
            get_ticket(person)
            lock.acquire()
    lock = Lock()
    for i in range(10):
            p = Process(target = ticket,args=( "person%s" %(i), lock))
            p.start()
    复制代码

    执行

    复制代码
    [root@node10 python]# python3 test.py
    person0查询余票:1
    person1查询余票:1
    person2查询余票:1
    person3查询余票:1
    person4查询余票:1
    person5查询余票:1
    person6查询余票:1
    person7查询余票:1
    person8查询余票:1
    person9查询余票:1
    person0抢到票
    person1没有买到票
    person2没有买到票
    person3没有买到票
    person4没有买到票
    person5没有买到票
    person6没有买到票
    person7没有买到票
    person8没有买到票
    person9没有买到票
    复制代码

    或者直接加锁

    复制代码
    import os
    import time,json
    from multiprocessing import Process,Lock
    def wr_info(sign,dic=None):
            if sign == "r":
                    with open("ticket",mode="r",encoding="utf-8") as fp:
                            dic = json.load(fp)
                    return dic
            elif sign == "w":
                    with open("ticket",mode="w",encoding="utf-8") as fp:
                            json.dump(dic,fp)
    
    #抢票方法
    def get_ticket(person):
            dic = wr_info("r")
            time.sleep(0.11)
            if dic["count"] > 0:
                    print("%s抢到票"%(person))
                    dic["count"] -=1
                    #更新数据库
                    wr_info("w",dic)
            else:
                    print ("%s没有买到票"%(person))
    
    
    #用ticket来进行统一调用
    #这里需要把lock传进来
    def ticket(person):
            #查询票数
            dic = wr_info("r")
            print ("%s查询余票:%s"%(person,dic['count']))
            lock.acquire()
            #开始抢票
            get_ticket(person)
            lock.release()
    
    lock = Lock()
    for i in range(10):
            p = Process(target = ticket,args=( "person%s"%(i),))
            p.start()
    复制代码

    区分同步和异步

    • 在产生进程对象的时候,进程之间是异步的.上锁之后,进程是同步的
    • 必须等上一个进程执行完毕之后,下一个进行才能执行,这个是同步.

    三  信号量

    Semaphore 本质上就是锁,只不过可以控制锁的数量

    模拟取钱,假设10个人排队取钱

    复制代码
    import os
    import time,json
    from multiprocessing import Process,Lock,Semaphore
    
    def bank(person):
            print ("%s进入柜台取钱"%(person))
            print ("%s取完离开"%(person))
    
    
    for i in range(10):
            p = Process(target = bank,args=("person%s"%(i),))
            p.start()
    复制代码

    执行

    复制代码
    [root@node10 python]# python3 test.py
    person0进入柜台取钱
    person0取完离开
    person1进入柜台取钱
    person1取完离开
    person2进入柜台取钱
    person2取完离开
    person3进入柜台取钱
    person3取完离开
    person4进入柜台取钱
    person4取完离开
    person5进入柜台取钱
    person5取完离开
    person6进入柜台取钱
    person6取完离开
    person7进入柜台取钱
    person7取完离开
    person8进入柜台取钱
    person8取完离开
    person9进入柜台取钱
    person9取完离开
    复制代码

    假设4个柜台使用semaphore上四把锁

    复制代码
    import os
    import time,json
    from multiprocessing import Process,Lock,Semaphore
    
    def bank(person):
            sem.acquire()
            time.sleep(5)
            print ("%s进入柜台取钱"%(person))
            print (os.getpid())
            res = os.popen("date").read()
            print(res)
            sem.release()
            print ("%s取完离开"%(person))
    
    sem = Semaphore(4)
    for i in range(10):
            p = Process(target = bank,args=("person%s"%(i),))
            p.start()
    复制代码

    执行

    复制代码
    person0进入柜台取钱
    person3进入柜台取钱
    4502
    4505
    Sat Feb 22 21:58:07 EST 2020
    Sat Feb 22 21:58:07 EST 2020
    
    
    person0取完离开
    person3取完离开
    person1进入柜台取钱
    4503
    Sat Feb 22 21:58:07 EST 2020
    
    person1取完离开
    person2进入柜台取钱
    4504
    Sat Feb 22 21:58:07 EST 2020
    
    person2取完离开
    person5进入柜台取钱
    4507
    Sat Feb 22 21:58:12 EST 2020
    
    person5取完离开
    person6进入柜台取钱
    4508
    Sat Feb 22 21:58:12 EST 2020
    
    person6取完离开
    person7进入柜台取钱
    person4进入柜台取钱
    4506
    4509
    Sat Feb 22 21:58:12 EST 2020
    
    person4取完离开
    Sat Feb 22 21:58:12 EST 2020
    
    person7取完离开
    person8进入柜台取钱
    4510
    Sat Feb 22 21:58:17 EST 2020
    
    person8取完离开
    person9进入柜台取钱
    4511
    Sat Feb 22 21:58:17 EST 2020
    
    person9取完离开
    复制代码

    根据时间,每次四个一次

    四 事件

    4.1 基本概念

    阻塞事件 :

    1. e = Event()生成事件对象e
    2. e.wait()动态给程序加阻塞 , 程序当中是否加阻塞完全取决于该对象中的is_set()

    [默认返回值是False]

    • 如果是True 不加阻塞
    • 如果是False 加阻塞

    控制这个属性的值

    •  set()方法 将这个属性的值改成True
    •  clear()方法 将这个属性的值改成False
    •  is_set()方法 判断当前的属性是否为True (默认上来是False)

    4.2 基本语法

    默认时False

    from multiprocessing import Process,Event
    e = Event()
    print (e.is_set())

    执行

    [root@node10 python]# python3 test.py
    False

    使用阻塞

    from multiprocessing import Process,Event
    e = Event()
    print (e.is_set())
    e.wait(5)   #相当于sleep
    print ("事件")

    执行

    [root@node10 python]# python3 test.py
    False
    事件

    set

    复制代码
    from multiprocessing import Process,Event
    e = Event()
    e.set()
    print (e.is_set())
    e.wait()
    print ("事件")
    复制代码

    执行,直接打印

    [root@node10 python]# python3 test.py
    True    #不加阻塞
    事件

    Claen

    复制代码
    e = Event() # True
    e.set()
    e.wait()
    print(123)
    e.clear() # False
    e.wait()
    print(456)
    复制代码

    执行,456不会打印,因为clean后时False

    [root@node10 python]# python3 test.py
    123

    4.3 模拟红绿灯效果

    复制代码
    from multiprocessing import Process,Event
    import time
    def traffic_light(e):
            #默认红灯先亮
            print ("red")
            while True:
                    if e.is_set():
                            #当前时绿灯
                            time.sleep(2)
                            #等完2秒,变红灯
                            print("red")
                            e.clear()
                    else:
                            #当前时红灯
                            time.sleep(2)
                            #等完2秒,变绿灯
                            print ("blue")
                            e.set()
    e = Event()
    traffic_light(e)
    复制代码

    执行

    复制代码
    [root@node10 python]# python3 test.py
    red
    blue
    red
    blue
    red
    复制代码

    模拟车辆遇到红灯停,绿灯行

    复制代码
    from multiprocessing import Process,Event
    import time,random
    def traffic_light(e):
            #默认红灯先亮
            print ("red")
            while True:
                    if e.is_set():
                            #当前时绿灯
                            time.sleep(2)
                            #等完2秒,变红灯
                            print("red")
                            e.clear()
                    else:
                            #当前时红灯
                            time.sleep(2)
                            #等完2秒,变绿灯
                            print ("blue")
                            e.set()
    
    def car(e,i):
            if not e.is_set():
                    print ("The car%s is wait"%(i))
                    e.wait()
            print("car%s is running"%(i))
    
    
    e = Event()
    p1 = Process(target=traffic_light,args=(e,))
    p1.start()
    
    for i in range(20):
            time.sleep(random.uniform(0,2))
            p2 = Process(target=car,args = (e,i))
            p2.start()
    复制代码

    执行

    复制代码
    [root@node10 python]# python3 test.py
    red
    The car0 is wait
    blue
    car0 is running
    car1 is running
    red
    The car2 is wait
    blue
    car2 is running
    car3 is running
    car4 is running
    red
    The car5 is wait
    blue
    car5 is running
    car6 is running
    red
    The car7 is wait
    The car8 is wait
    The car9 is wait
    The car10 is wait
    blue
    car10 is running
    car8 is running
    car9 is running
    car7 is running
    car11 is running
    red
    The car12 is wait
    blue
    car12 is running
    car13 is running
    car14 is running
    red
    The car15 is wait
    The car16 is wait
    blue
    car15 is running
    car16 is running
    car17 is running
    car18 is running
    red
    The car19 is wait
    blue
    car19 is running
    red
    复制代码

    4.4 使用守护进程

    复制代码
    from multiprocessing import Process,Event
    import time,random
    def traffic_light(e):
            #默认红灯先亮
            print ("red")
            while True:
                    if e.is_set():
                            #当前时绿灯
                            time.sleep(2)
                            #等完2秒,变红灯
                            print("red")
                            e.clear()
                    else:
                            #当前时红灯
                            time.sleep(2)
                            #等完2秒,变绿灯
                            print ("blue")
                            e.set()
    
    def car(e,i):
            if not e.is_set():
                    print ("The car%s is wait"%(i))
                    e.wait()
            print("car%s is running"%(i))
    
    
    e = Event()
    p1 = Process(target=traffic_light,args=(e,))
    p1.daemon = True
    p1.start()
    
    for i in range(20):
            time.sleep(random.uniform(0,2))
            p2 = Process(target=car,args = (e,i))
            p2.start()
    复制代码

    执行

    复制代码
    red
    The car0 is wait
    The car1 is wait
    The car2 is wait
    blue
    car0 is running
    car1 is running
    car2 is running
    car3 is running
    car4 is running
    car5 is running
    car6 is running
    red
    The car7 is wait
    The car8 is wait
    The car9 is wait
    The car10 is wait
    blue
    car8 is running
    car7 is running
    car9 is running
    car10 is running
    car11 is running
    red
    The car12 is wait
    blue
    car12 is running
    car13 is running
    car14 is running
    red
    The car15 is wait
    blue
    car15 is running
    car16 is running
    car17 is running
    red
    The car18 is wait
    The car19 is wait
    复制代码

    卡在这里不执行,是因为car已经跑完,进程不再执行,卡在e.wait这里

    使用join

    复制代码
    from multiprocessing import Process,Event
    import time,random
    def traffic_light(e):
            #默认红灯先亮
            print ("red")
            while True:
                    if e.is_set():
                            #当前时绿灯
                            time.sleep(2)
                            #等完2秒,变红灯
                            print("red")
                            e.clear()
                    else:
                            #当前时红灯
                            time.sleep(2)
                            #等完2秒,变绿灯
                            print ("blue")
                            e.set()
    
    def car(e,i):
            if not e.is_set():
                    print ("The car%s is wait"%(i))
                    e.wait()
            print("car%s is running"%(i))
    
    
    e = Event()
    lst = []
    p1 = Process(target=traffic_light,args=(e,))
    p1.daemon = True
    p1.start()
    
    for i in range(20):
            time.sleep(random.uniform(0,2))
            p2 = Process(target=car,args = (e,i))
            p2.start()
            lst.append(p2)
    for i in lst:
            i.join()
    print("程序彻底结束;")
    复制代码

    执行

    复制代码
    red
    The car0 is wait
    The car1 is wait
    blue
    car1 is running
    car0 is running
    car2 is running
    car3 is running
    red
    The car4 is wait
    blue
    car4 is running
    car5 is running
    car6 is running
    car7 is running
    red
    The car8 is wait
    The car9 is wait
    blue
    car9 is running
    car8 is running
    car10 is running
    red
    The car11 is wait
    blue
    car11 is running
    car12 is running
    car13 is running
    car14 is running
    red
    The car15 is wait
    blue
    car15 is running
    car16 is running
    car17 is running
    red
    The car18 is wait
    The car19 is wait
    blue
    car19 is running
    car18 is running
    程序彻底结束;
    复制代码
    学习记录,小白一枚
  • 相关阅读:
    使用.htaccess文件
    让apache支持htaccess文件
    使用SendMessage进行进程间通信
    【Codeforces Round #505 (Div. 1 + Div. 2) 】
    【Educational Codeforces Round 49 (Rated for Div. 2) 】
    【Codeforces Round #504 (Div. 1 + Div. 2) 】
    【2018 Multi-University Training Contest 10】
    【2018 Multi-University Training Contest 9】
    【2018 Multi-University Training Contest 8】
    【2018 Multi-University Training Contest 7】
  • 原文地址:https://www.cnblogs.com/wangsirde0428/p/14322771.html
Copyright © 2020-2023  润新知