博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python并发编程03/僵尸孤儿进程,互斥锁,进程之间的通信
阅读量:5262 次
发布时间:2019-06-14

本文共 6200 字,大约阅读时间需要 20 分钟。

目录

Python并发编程03/僵尸孤儿进程,互斥锁,进程之间的通信

1.昨日回顾

1.创建进程的两种方式: 函数, 类.2.pid: os.getpid()  os.getppid()  tasklist   tasklist| findstr  进程名3.进程与进程之间是有物理隔离: 不能共享内存的数据.(lock,队列)4.join阻塞:  让主进程等待子进程结束之后,在执行.5.其他属性: terminate() is_alive() name,6.守护进程: 将子进程设置成守护进程,当主进程结束了,子进程就马上结束.

2.僵尸进程和孤儿进程

2.1僵尸进程

僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中,这种进程称之为僵尸进程.#基于unix环境(linux,macOS)    #主进程需要等待子进程结束之后,主进程才结束主进程时刻监测子进程的运行状态,当子进程结束之后,一段时间之内,将子进程进行回收.#为什么主进程不在子进程结束后马上对其回收呢?# 1. 主进程与子进程是异步关系.主进程无法马上捕获子进程什么时候结束.# 2. 如果子进程结束之后马上再内存中释放资源,主进程就没有办法监测子进程的状态了.#unix针对于上面的问题,提供了一个机制.#所有的子进程结束之后,立马会释放掉文件的操作链接,内存的大部分数据,但是会保留一些内容: 进程号,结束时间,运行状态,等待主进程监测,回收.僵尸进程: 所有的子进程结束之后,在被主进程回收之前,都会进入僵尸进程状态.#僵尸进程有无危害???#如果父进程不对僵尸进程进行回收(wait/waitpid),产生大量的僵尸进程,这样就会占用内存,占用进程pid号.

2.2孤儿进程

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

2.3僵尸进程如何解决?

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

3.互斥锁,锁

3.1互斥锁的应用

# 三个同事 同时用一个打印机打印内容.# 三个进程模拟三个同事, 输出平台模拟打印机.# 版本一:# 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()# 现在是所有的进程都并发的抢占打印机,# 并发是以效率优先的,但是目前我们的需求: 顺序优先.# 多个进程共强一个资源时, 要保证顺序优先: 串行,一个一个来.# 版本二:# 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()# 我们利用join 解决串行的问题,保证了顺序优先,但是这个谁先谁后是固定的.# 这样不合理. 你在争抢同一个资源的时候,应该是先到先得,保证公平.# 版本3:from multiprocessing import Processfrom multiprocessing import Lockimport timeimport randomimport osdef 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()

1730001-20190821224327889-2098072863.png

3.2Lock与join的区别

#共同点: 都可以把并发变成串行, 保证了顺序.#不同点: join人为设定顺序,lock让其争抢顺序,保证了公平性.

4.进程之间的通信

进程在内存级别是隔离的

4.1基于文件通信 (抢票系统)

# 抢票系统.# 1. 先可以查票.查询余票数.  并发# 2. 进行购买,向服务端发送请求,服务端接收请求,在后端将票数-1,返回到前端. 串行.# from multiprocessing import Process# 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():#     search()#     paid()### if __name__ == '__main__':##     for i in range(6):#         p = Process(target=task)#         p.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()# 当很多进程抢一个资源(数据)时, 你要保证顺序(数据的安全),一定要串行.# 互斥锁: 可以公平性的保证顺序以及数据的安全.# 基于文件的进程之间的通信:    # 效率低.    # 自己加锁麻烦而且很容易出现死锁.

1730001-20190821224350572-1129706455.png

4.2基于队列通信

队列: 把队列理解成一个容器,这个容器可以承载一些数据,队列的特性: 先进先出永远保持这个数据. 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 只要遇到阻塞就会报错.

1730001-20190821224421086-543840746.png

转载于:https://www.cnblogs.com/liubing8/p/11391721.html

你可能感兴趣的文章
C 筛选法找素数
查看>>
TCP为什么需要3次握手与4次挥手(转载)
查看>>
IOC容器
查看>>
Windows 2003全面优化
查看>>
URAL 1002 Phone Numbers(KMP+最短路orDP)
查看>>
web_day4_css_宽度
查看>>
electron入门心得
查看>>
格而知之2:UIView的autoresizingMask属性探究
查看>>
我的Hook学习笔记
查看>>
js中的try/catch
查看>>
寄Android开发Gradle你需要知道的知识
查看>>
简述spring中常有的几种advice?
查看>>
整理推荐的CSS属性书写顺序
查看>>
ServerSocket和Socket通信
查看>>
css & input type & search icon
查看>>
源代码的下载和编译读后感
查看>>
Kafka学习笔记
查看>>
Octotree Chrome安装与使用方法
查看>>
Windows 环境下基于 Redis 的 Celery 任务调度模块的实现
查看>>
趣谈Java变量的可见性问题
查看>>