一.进程理论
1.什么是进程,与程序的区别
程序是一堆代码,而进程是指正在运行的程序
进程是一个实体,每一个进程都有它自己独立的内存空间
2.同步和异步:针对任务的提交方式
同步:提交任务后原地等待任务的返回结果,期间不做任何事
异步:提交任务后,不等待任务的返回结果,直接运行下一行代码
3.阻塞和非阻塞:针对程序运行的状态
阻塞:遇到IO操作>>> 阻塞态
非阻塞:就绪或者运行态>>> 就绪态,运行态
二.开启进程的两种方式
1.直接通过Process类创建进程
from multiprocessing import Process
import time
def task(name):
print('%s is running' % name)
time.sleep(3)
print('%s is over' % name)
# 注意:在windows系统中,创建进程会将代码以模块的方式从头到尾家在一遍
一定要写在if __name__ == '__main__':代码中,不然会产生循环导入
# 强调:函数名一旦加括号,执行优先级最高,立刻执行
if __name__ == '__main__':
p = Process(target = task,args = ('egon',)) # 实例化出一个对象
p.start() # 告诉操作系统创建一个进程
print('主')
2.通过自定义类继承Process类来创建进程
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,name)
super().__init__()
self.name = name
# 必须写run方法
def run(self):
print('%s is running' % self.name)
time.sleep(3)
print('%s is over' % self.name)
if __name__ == '__main__':
obj = MyProcess('egon')
obj.start()
print('主')
三.进程对象的join方法
from multiprocessing import Process
import time
def task(name,n):
print('%s is running' % name)
time.sleep(n)
print('%s is over' % name)
if __name__ == '__main__':
start_time = time.time()
p_list = []
for i in range(3):
p = Process(target=task, args=('子进程%s' % i,i))
p.start()
p_list.append(p)
for i in p_list:
i.join()
print('主',time.time()-start_time)
# join的作用仅仅只是让主进程等待子进程的结束,不会影响其他子进程的运行
四.进程之间内存隔离
from multiprocessing import Process
x = 100
def task():
global x
x = 1
if __name__ == '__main__'
p = Process(target=task)
p.start()
p.join()
print('主',x) # 100
五.进程对象的其他相关方法
from multiprocessing import Process, current_process
import time
import os
def task():
print('%s is running' % os,getpid()) # % current_process().pid
time.sleep(3)
print('%s is over' % os.getppid()) # 获取父进程PID
if __name__ == '__main__':
p = Process(target=task)
p.start()
# p.terminate() # 杀死子进程
# print(p.is_alive()) # 判断子进程是否存活
print('主')
六.僵尸进程与孤儿进程
僵尸进程:两种情况下会回收子进程的pid等信息
1.父进程正常结束
2.join方法
孤儿进程:父进程意外死亡
linux下: init进程用来回收孤儿进程所占用的资源
ps aux |grep 'Z'
七.守护进程
from multiprocessing import Process
import time
def task(name):
print('%s 活着' % name)
time.sleep(3)
print('%s 正常死亡' % name)
if __name__ == '__main__':
p = Process(target=task, args=('egon',))
p.daemon = True # 必须在p.start()开启进程命令之前声明
p.start()
print('主进程死亡') # 守护进程无论什么状态都直接死亡
八.互斥锁(千万不能随意去使用)
牺牲了效率但是保证了数据的安全
from multiprocessing import Process,Lock import json import time import random def search(i): with open('info','r',encoding='utf-8') as f: data = json.load(f) print('用户查询余票数:%s'%data.get('ticket')) def buy(i): # 买票之前还得先查有没有票! with open('info','r',encoding='utf-8') as f: data = json.load(f) time.sleep(random.randint(1,3)) # 模拟网络延迟 if data.get('ticket') >0: data['ticket'] -= 1 # 买票 with open('info','w',encoding='utf-8') as f: json.dump(data,f) print('用户%s抢票成功'%i) else: print("用户%s查询余票为0"%i) def run(i,mutex): search(i) mutex.acquire() # 抢锁 一把锁不能同时被多个人使用,没有抢到的人,就一直等待锁释放 buy(i) mutex.release() # 释放锁 if __name__ == '__main__': mutex = Lock() for i in range(10): p = Process(target=run,args=(i,mutex)) p.start()
锁一定要在主进程中创建,给子进程去用
解决多个进程操作同一份数据,造成数据不安全的情况
加锁会将并发变成串行
锁通常用在对数据操作的部分,并不是对进程全程加锁