进程
进程理论
程序:一堆代码
进程:正在运行的程序
进程是一个实体。每一个进程都有他独立的内存空间
同步和异步:针对任务的提交方式
同步:提交任务之后原地等待任务的返回结果,期间不做任何事
异步:提交任务之后,不等待任务的返回结果,执行运行下一行代码
阻塞与非阻塞:针对程序运行的状态
阻塞:遇到IO操作 >>>阻塞态
非阻塞:就绪或者运行态 >>>就绪态,运行态
开启进程的两种运行方式
方法一:
from multiprocessing import Process
def task(name)
print(name)
#在windows系统中,因为是以导包的方式来给新的子进程添加上与主进程相同的属性, 所以一定要在文件自执行的情况下运行,不然会进入死循环
if __name__='__main__':
#task不能加上括号,不然会直接执行,因为函数的调用优先级是最高的
p=Process(target=task,args=('wo',))
p.start()#发送型号给操作系统,让操作系统创建一个新的进程
pritn('主')
方法二
from multiprocess import Process
class Myprocess(Process):
def __init__(self,name):
self.name=name
super().__init__()#在添加自己的属性后,完全的copy父类中的init
def run(self):#必须是run因为run其实是Process的内置方法
print('%s is running'%self.name)
if __name__='__main__':
p=Myprocess('wo')
p.start()
print('主')
进程对象的join方法
方法一:
from multiprocessing import Process
def task(name)
print(name)
if __name__='__main__':
lis=[]
for i in range(1,4)
p=Process(target=task,args=('%s'%i,))
p.start()
lis.append(p)
for j in lis:
p.join()#在子进程全部结束后才会执行主进程,同时join会清理子进程的全部内存(包括PID信息等数据),子程序之间互不影响,只针对主进程有影响。
pritn('主')
进程之间内存隔离
from multiprocessing import Process
a=100
def task()
global a
a=0
if __name__='__main__':
p==Process(target=task)
p.start()
p.join()#确保子进程优先执行
print(a)# 结果为100
#结果为100说明,主进程与子进程虽然共享一个内存空间,这其实就是多道技术中空间上复用的一种体现,但是两者直接是存在物理隔离的,所以互不影响
进程对象其他相关方法
得到pid的方法一
from multiprocessing import Process,current_process
def task()
print(curre_process().pid)#打印子进程的pid
if __name__='__main__':
p==Process(target=task)
p.start()
print(current_process().pid)#打印主进程的pid
方法二
from multiprocessing import Process
import os
def task()
print(os.getpid())#打印子进程的pid
print(os.getppid())#打印子进程的父进程的pid(这里其实就是主进程)
if __name__='__main__':
p==Process(target=task)
p.start()
print(os.getpid())#打印主进程的pid
print(os.getppid())#取决于运行python程序的应用软件
僵尸进程与孤儿进程
僵尸进程:子进程运行结束后,内存释放,但是仍然占有pid等数据信息,提供父进程使用。
二种情况下会回收子进程的pid信息
1.父进程正常结束
2.join方法
孤儿进程:父进程意外死亡
linux中:init就像是孤儿院,用来回收孤儿进程所占用的资源
ps aux |grep 'Z'
进程创建守护进程
其一:守护进程会在主进程代码执行结束后就终止
其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children
注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即终止
互斥锁
1.牺牲效率来保证了数据的安全
2.锁一定要在主进程中创建,在子进程中使用
3.解决多个进程操作同一份数据,造成数据不安全的情况
4.加锁会把并发变成串行
5.一把锁不能多人使用,没有抢到的只能一直等待锁释放
#抢票案例,文件中的数据为{"cart":1}
from multiprocessing import Process,Lock #导入Lock模块
import json
import time
import os
def look(name):
with open('a','r')as r:
num=json.load(r)
print('%s查询还有%s张票'%(name,num['cart']))
def get(name):
with open('a','r')as r:
num = json.load(r)
time.sleep(3) #模拟网络延时
if num['cart']>= 1:
num['cart']-=1
with open('a','w')as w:
json.dump(num,w)
print('%s购票成功'%name)
else:
print('没有票了')
def run(name,lock1):
look(name)
lock1.acquire() #抢锁
get(name)
lock1.release() #释放锁
if __name__ == '__main__':
lock1=Lock() #其实就是生产一个对象
for i in range(1,4):
p=Process(target=run,args=(i,lock1))
p.start()
print('RUA')