26、僵尸进程&孤儿进程、守护进程、互斥锁
Day 25
一、僵尸进程与孤儿进程
孤儿进程:当父进程已经结束,而子进程还在运行,子进程就成为孤儿进程,有其存在的必要性,没有不良影响。
僵尸进程:当一个进程已经结束了,但是它仍然有一些数据存在,此时称之为僵尸进程(PID是有限的,僵尸进程过多会导致无法开启新的进程)
在linux中,有这么一个机制,父进程无论什么时候都可以获取到子进程的一些数据
子进程 任务执行完毕后,确实结束了,但是仍然保留一些数据 目的是为了让父进程能够获取这些信息
python中已经在start等功能中封装了这些操作,无需关心
二、守护进程
在python中,守护进程也是一个进程
默认情况下 主进程即使代码执行完毕了 也会等待子进程 是为了避免成为孤儿.
当一个进程b设置为另一进程a的守护进程时,a是被守护,b是守护进程
特点:当被守护的a结束时,即使b的任务没有完成也会随之结束
from multiprocessing import Process
import time
def task():
print('son run')
time.sleep(3)
print('son over')
if __name__ == '__main__':
p = Process(target=task)
p.daemon = True # 是布尔类型,默认为False,要在start之前
p.start() # 如果只运行一次可以这么写
print('Dad')
三、进程安全问题—互斥锁
进程安全问题
当并发的多个任务,要同时操作同一个资源,就会造成数据错乱的问题
解决的方法是,将并发操作公共资源的代码 由并发变为串行 解决了安全问题,但是牺牲了效率
-
方式一
直接使用join函数
缺点:将任务中所有代码全都串行,此时还是不如不要开进程
多个进程之间原本是公平竞争,join强行规定了执行顺序
from multiprocessing import Process
def task1():
print('name is nick')
print('gender is girl')
print('age is 18')
def task2():
print('name is bgon')
print('gender is oldman')
print('age is 48')
if __name__ == '__main__':
p1 = Process(target=task1)
p2 = Process(target=task2)
p1.start()
p2.start()
# p1.join()#可以解决
# p2.join()#但是效率非常低低低,不是最好的解决方案
-
方式二:
互斥锁 重点
其原理又是将要操作公共资源的代码锁起来🔒,保证同一时间只能有一个进程在执行这部分代码
锁其实只是给执行的代码加了限制
from multiprocessing import Process, Lock
import time, random
mutex = Lock() # 造锁
def task1(mutex):
mutex.acquire() # 加锁
print('name is nick')
time.sleep(random.random())
print('gender is girl')
time.sleep(random.random())
print('age is 18')
mutex.release() # 解锁
def task2(mutex):
mutex.acquire() # 加锁
print('name is bgon')
time.sleep(random.random())
print('gender is oldman')
time.sleep(random.random())
print('age is 48')
mutex.release() # 解锁
if __name__ == '__main__':
p1 = Process(target=task1,args=(mutex,))
p2 = Process(target=task2,args=(mutex,))
p1.start()
p2.start()
# p1.join()#可以解决
# p2.join()#但是效率非常低低低
四、模拟抢票小案例
from multiprocessing import Process, Lock
import json
def show():
with open("db.json") as f:
data = json.load(f)
print("剩余票数", data["count"])
def buy():
with open("db.json") as f:
data = json.load(f)
if data["count"] > 0:
data["count"] -= 1
with open("db.json", "wt") as f2:
json.dump(data, f2)
print("抢票成功!")
def task(mutex):
show()
mutex.acquire()
buy()#对于买这个操作,增加限制
mutex.release()
if __name__ == '__main__':
mutex = Lock()
for i in range(5):
p = Process(target=task, args=(mutex,))
p.start()