并发编程--多进程教程
并发编程-多进程
并发
======================================================
并发指的是多个任务同时被执行,并发编程指的是编写支持多任务并发的应用程序。
进程
进程指的是正在运行的程序,是一系列过程的统称,也是操作系统在调度和进行资源分配的基本单位
进程是实现并发的一种方式
一个程序可以产生多个进程
PID和PPID
PID:系统给进程的编号
PPID:当一个进程a开启了另一个进程b,那么a被称为b的父进程。当pycharm运行了py文件,那么pycharm就是py文件的父进程
并行与并发,阻塞与非阻塞
并发指的是,多个事件同时发生了,需要一直切换完成
并行指的是,多个事件同时进行,互不影响
阻塞状态是因为程序遇到了IO操作,或是sleep,导致后续的代码不能被CPU执行
非阻塞与之相反,表示程序正在被CPU执行。
进程有三种状态,就绪态,运行态,阻塞态
python中实现多进程
python中开启子进程的两种方式
方式1:实例化Process类
<pre class="python">```
from multiprocessing import Process
import time
def task(name):
print(f'{name} is running ')
time.sleep(3)
print('f{name} is fone')
if __name__=='__main__':
#在windows系统之上,开启子进程的操作一定要放在这个里面
#Process(target=task,kwargs={'name':egon})
p=Process(target=task,args=('jack',))#参数放在元祖里
p.start() # 向操作系统发送请求,操作系统会申请内存空间,然后把父进程的数据拷贝给子进程,作为子进程的初始状态
print('主')
方式2:继承Process,并覆盖run方法
<pre class="python">```
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,name):
super(MyProcess,self).__init__()
self.name=name
def run(self):
print('%s is running' %self.name)
time.sleep(3)
print('%s is done' %self.name)
if __name__ == '__main__':
p=MyProcess('jack')
p.start()
print('主')
需要注意的是
1.在windows下 开启子进程必须放到__main__
下面,因为windows在开启子进程时会重新加载所有的代码造成递归创建进程
2.第二种方式中,必须将要执行的代码放到run方法中,子进程只会执行run方法其他的一概不管
3.start仅仅是给操作系统发送消息,而操作系统创建进程是要花费时间的,所以会有两种情况发送
3.1开启进程速度慢于程序执行速度,先打印”主“ 在打印task中的消息
3.2开启进程速度快于程序执行速度,先打印task中的消息,在打印”主“
进程间内存相互隔离
在一个进程内修改了全局变量,其他进程不受影响。就像是运行两个文件,一个修改了,另外一个不受影响。
<pre class="python">```
from multiprocessing import Process
import time
x=1000
def task():
global x
x=0
print('儿子死啦',x)
if __name__ == '__main_
print(x)
p=Process(target=task)
p.start()
time.sleep(5)
print(x)
###
1000
儿子死啦 0
1000
join函数:
可以让一个进程等待另一个进程结束后再运行
<pre class="python">```
from multiprocessing import Process
import time
x=1000
def task():
time.sleep(3)
global x
x=0
print('儿子死啦',x)
if __name__ == '__main__':
p=Process(target=task)
p.start()
p.join() # 让父亲在原地等,如果不加join函数,则会先执行print(x)
print(x)
<pre class="python">```
from multiprocessing import Process
import time,random
x=1000
def task(n):
print('%s is runing' %n)
time.sleep(n)
if __name__ == '__main__':
start_time=time.time()
p1=Process(target=task,args=(1,))
p2=Process(target=task,args=(2,))
p3=Process(target=task,args=(3,))
p1.start()
p2.start()
p3.start()
p3.join() #3s
p1.join()
p2.join()
print('主',(time.time() - start_time))
start_time=time.time()
p_l=[]
for i in range(1,4):
p=Process(target=task,args=(i,))
p_l.append(p)
p.start()
for p in p_l:
p.join()
print('主',(time.time() - start_time))
Process对象常用属性
<pre class="python">```
from multiprocessing import Process
def task(n):
print('%s is runing' %n)
time.sleep(n)
if __name__ == '__main__':
start_time=time.time()
p1=Process(target=task,args=(1,),name='任务1')
p1.start() # 启动进程
print(p1.pid) # 获取进程pid
print(p1.name) # 获取进程名字
p1.terminate() # 终止进程
p1.join() # 提高优先级
print(p1.is_alive()) # 获取进程的存活状态
print('主')
孤儿进程和僵尸进程
孤儿进程:
指的是开启子进程后,父进程先于子进程终止了,那这个子进程就称之为孤儿进程。
孤儿进程是无害的,有其存在的必要性,在父进程结束后,其子进程会被操作系统接管。
僵尸进程:
指的是当父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程会成为一个僵尸进程,这种情况只在linux下出现。因为windows中进程完全是独立的没有任何关联。
如果父进程先退出,子进程被操作系统接管,子进程退出后操作系统会回收其占用的相关资源,
python已经帮我们自动处理了僵尸进程的回收工作。