? 主进程需要等待子进程结束之后, 主进程才结束
? 主进程时刻监测子进程的运行状态, 当子进程结束之后, 一段时间之内, 将子进程进行回收
? 主进程与子进程是异步关系, 主进程无法马上捕获子进程什么时候结束
? 如果子进程结束之后, 马上在内存中释放资源, 主进程就没有办法监测子进程的状态了
? 所有的子进程结束之后, 立马会释放掉文件的操作链接, 内存的大部分数据, 但是会保留一些内容: 进程号, 结束时间, 运行状态. 等待主进程监测, 回收.
? 所有的子进程结束之后, 在被主进程回收之前, 都会进入僵尸进程状态
? 如果父进程不对僵尸进程进行回收(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()
"""
188412开始打印了
188408开始打印了
188388开始打印了
188412打印结束了
188388打印结束了
188408打印结束了
"""
# 现在是所有的进程都并发的抢占打印机,
# 并发是以效率优先的, 但是目前我们的需求: 顺序优先
# 多个进程共抢一个资源时, 要保证顺序优先: 串行, 一个一个来
# 版本二
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()
p1.join()
p2.start()
p2.join()
p3.start()
p3.join()
"""
160876开始打印了
160876打印结束了
188264开始打印了
188264打印结束了
188328开始打印了
188328打印结束了
"""
# 我们利用join, 解决串行的问题, 保证了顺序优先, 但是这个谁先谁后是固定的.
# 这样不合理, 你在争抢同一个资源的时候, 应该是先到先得, 保证公平
# 版本三
from multiprocessing import Process
from multiprocessing import Lock
import time
import random
def task1(p, lock):
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))
p1.start()
p2.start()
p3.start()
"""
p1开始打印了
p1打印结束了
p2开始打印了
p2打印结束了
p3开始打印了
p3打印结束了
"""
? 都可以把并发变成串行, 保证了顺序
? join 认为设定顺序, lock 让其争抢顺序, 保证了公平性
? 进程在内存级别是隔离的, 但是文件在磁盘上
? 利用抢票系统讲解
# 抢票系统
# 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", "r", encoding="utf-8")as f:
dic = json.load(f)
print(f"{os.getpid()}查看了票数, 剩余{dic['count']}")
def paid():
with open("ticket.json", "r", encoding="utf-8")as f:
dic = json.load(f)
if dic["count"] > 0:
dic["count"] -= 1
time.sleep(random.randint(1, 3))
with open("ticket.json", "w", encoding="utf-8")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 f:
dic = json.load(f)
print(f"{os.getpid()} 查看了票数, 剩余{dic['count']}")
def paid():
with open("ticket.json", encoding="utf-8")as f:
dic = json.load(f)
if dic["count"] > 0:
dic["count"] -= 1
time.sleep(random.randint(1, 3))
with open("ticket.json", "w", encoding="utf-8")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()
"""
203496 查看了票数, 剩余3
203512 查看了票数, 剩余3
203496购买成功
203504 查看了票数, 剩余2
203480 查看了票数, 剩余2
203488 查看了票数, 剩余2
203520 查看了票数, 剩余2
203512购买成功
203504购买成功
"""
# 当很多进程共抢一个资源(数据)时, 你要保证顺序(数据的安全), 一定要串行.
# 互斥锁: 可以公平性的保证顺序以及数据的安全
# 基于文件的进程之间的通信:
# 效率低
# 自己加锁麻烦而且很容易出现死锁
原文:https://www.cnblogs.com/beichen123/p/11391594.html