• python_高级进阶(2)进程与并发


    基于unix环境(linux,macOS)

    主进程需要等待子进程结束之后,主进程才结束
    主进程时刻监测子进程的运行状态,当子进程结束之后,一段时间之内,将子进程进行回收.
    为什么主进程不在子进程结束后马上对其回收呢?
    主进程与子进程是异步关系.主进程无法马上捕获子进程什么时候结束.
    如果子进程结束之后马上再内存中释放资源,主进程就没有办法监测子进程的状态了.
    unix针对于上面的问题,提供了一个机制.
    所有的子进程结束之后,立马会释放掉文件的操作链接,内存的大部分数据,但是会保留一些内容: 进程号,结束时间,运行状态,等待主进程监测,回收.

    僵尸进程:

    所有的子进程结束之后,在被主进程回收之前,都会进入僵尸进程状态.

    僵尸进程缺点:

    如果父进程不对僵尸进程进行回收(wait/waitpid),产生大量的僵尸进程,这样就会占用内存,占用进程pid号.

    僵尸进程如何解决

    父进程产生了大量子进程,但是不回收,这样就会形成大量的僵尸进程,
    解决方式就是直接杀死父进程,将所有的僵尸进程变成孤儿进程进程,由init进行回收.

    孤儿进程

    父进程由于某种原因结束了,但是你的子进程还在运行中,
    这样你的这些子进程就成了孤儿进程.你的父进程如果结束了,
    你的所有的孤儿进程就会被init进程的回收,init就变成了你的父进程,对你进行回收.

    串行

    并发是以效率优先的,但是目前我们的需求: 顺序优先.
     多个进程共强一个资源时, 要保证顺序优先: 串行,一个一个来
    由并发变成了串行,牺牲了运行效率,但避免了竞争
     from multiprocessing import Process
     import time
     import random
     import os
    
     def task1():
         print(f'{os.getpid()}开始打印了')
         time.sleep(random.randint(1,3))
         print(f'{os.getpid()}打印结束了')
    
     def task2():
         print(f'{os.getpid()}开始打印了')
         time.sleep(random.randint(1,3))
         print(f'{os.getpid()}打印结束了')
    
     def task3():
         print(f'{os.getpid()}开始打印了')
         time.sleep(random.randint(1,3))
         print(f'{os.getpid()}打印结束了')
    
     if __name__ == '__main__':
    
         p1 = Process(target=task1)
         p2 = Process(target=task2)
         p3 = Process(target=task3)
    
         p1.start()
         p2.start()
         p3.start()
    加锁:由并发变成了串行,牺牲了运行效率,但避免了竞争
    

    使用join阻塞版本

    from multiprocessing import Process
     import time
     import random
     import os
    
     def task1(p):
         print(f'{p}开始打印了')
         time.sleep(random.randint(1,3))
         print(f'{p}打印结束了')
    
     def task2(p):
         print(f'{p}开始打印了')
         time.sleep(random.randint(1,3))
         print(f'{p}打印结束了')
    
     def task3(p):
         print(f'{p}开始打印了')
         time.sleep(random.randint(1,3))
         print(f'{p}打印结束了')
    
     if __name__ == '__main__':
    
         p1 = Process(target=task1,args=('p1',))
         p2 = Process(target=task2,args=('p2',))
         p3 = Process(target=task3,args=('p3',))
    
         p2.start()
         p2.join()
         p1.start()
         p1.join()
         p3.start()
         p3.join()
    
    

    互斥锁,锁.

    lock与join的区别.
    共同点: 都可以把并发变成串行, 保证了顺序.
    不同点: join人为设定顺序,lock让其争抢顺序,保证了公平性.
    from multiprocessing import Process
    from multiprocessing import Lock
    import time
    import random
    import os
    
    def task1(p,lock):
        '''
        一把锁不能连续锁两次
        lock.acquire()
        lock.acquire()
        lock.release()
        lock.release()
        '''
        lock.acquire()
        print(f'{p}开始打印了')
        time.sleep(random.randint(1,3))
        print(f'{p}打印结束了')
        lock.release()
    
    def task2(p,lock):
        lock.acquire()
        print(f'{p}开始打印了')
        time.sleep(random.randint(1,3))
        print(f'{p}打印结束了')
        lock.release()
    
    def task3(p,lock):
        lock.acquire()
        print(f'{p}开始打印了')
        time.sleep(random.randint(1,3))
        print(f'{p}打印结束了')
        lock.release()
    
    if __name__ == '__main__':
    
        mutex = Lock()
        p1 = Process(target=task1,args=('p1',mutex))
        p2 = Process(target=task2,args=('p2',mutex))
        p3 = Process(target=task3,args=('p3',mutex))
    
        p2.start()
        p1.start()
        p3.start()
    

    进程之间的通信:

    # from multiprocessing import Process
    # from multiprocessing import Lock
    # import json
    # import time
    # import os
    # import random
    #
    #
    # def search():
    #     time.sleep(random.randint(1,3))  # 模拟网络延迟(查询环节)
    #     with open('ticket.json',encoding='utf-8') as f1:
    #         dic = json.load(f1)
    #         print(f'{os.getpid()} 查看了票数,剩余{dic["count"]}')
    #
    #
    # def paid():
    #     with open('ticket.json', encoding='utf-8') as f1:
    #
    #         dic = json.load(f1)
    #     if dic['count'] > 0:
    #         dic['count'] -= 1
    #         time.sleep(random.randint(1,3))  # 模拟网络延迟(购买环节)
    #         with open('ticket.json', encoding='utf-8',mode='w') as f1:
    #             json.dump(dic,f1)
    #         print(f'{os.getpid()} 购买成功')
    #
    #
    # def task(lock):
    #     search()
    #     lock.acquire()
    #     paid()
    #     lock.release()
    #
    # if __name__ == '__main__':
    #     mutex = Lock()
    #     for i in range(6):
    #         p = Process(target=task,args=(mutex,))
    #         p.start()
    
    
    # 当很多进程抢一个资源(数据)时, 你要保证顺序(数据的安全),一定要串行.
    # 互斥锁: 可以公平性的保证顺序以及数据的安全.
    
    # 基于文件的进程之间的通信:
        # 效率低.
        # 自己加锁麻烦而且很容易出现死锁.
    

    基于队列通信

    队列: 把队列理解成一个容器,这个容器可以承载一些数据,
    队列的特性: 先进先出永远保持这个数据. FIFO(first in first out).
    # from multiprocessing import Queue
    # q = Queue()
    # def func():
    #     print('in func')
    # q.put(1)
    # q.put('alex')
    # q.put([1,2,3])
    # q.put(func)
    #
    #
    # print(q.get())
    # print(q.get())
    # print(q.get())
    # f = q.get()
    # f()
    
    
    # from multiprocessing import Queue
    # q = Queue(3)
    #
    # q.put(1)
    # q.put('alex')
    # q.put([1,2,3])
    # # q.put(5555)  # 当队列满了时,在进程put数据就会阻塞.
    # # q.get()
    #
    # print(q.get())
    # print(q.get())
    # print(q.get())
    # print(q.get())  # 当数据取完时,在进程get数据也会出现阻塞,直到某一个进程put数据.
    
    
    # from multiprocessing import Queue
    # q = Queue(3)  # maxsize
    #
    # q.put(1)
    # q.put('alex')
    # q.put([1,2,3])
    # q.put(5555,block=False)
    #
    # print(q.get())
    # print(q.get())
    # print(q.get())
    # print(q.get(timeout=3))  # 阻塞3秒,3秒之后还阻塞直接报错.
    # print(q.get(block=False))
    
    # block=False 只要遇到阻塞就会报错.
    
  • 相关阅读:
    LeetCode 449. Serialize and Deserialize BST
    LeetCode Word Abbreviation
    LeetCode 402. Remove K Digits
    LeetCode 439. Ternary Expression Parser
    LeetCode Frog Jump
    LeetCode 630. Course Schedule III
    LeetCode 729. My Calendar I
    LeetCode 567. Permutation in String
    LeetCode Find Permutation
    LeetCode Number of Atoms
  • 原文地址:https://www.cnblogs.com/SkyRabbit/p/11389619.html
Copyright © 2020-2023  润新知