并发编程--多进程

并发编程-多进程

并发

并发指的是多个任务同时被执行,并发编程指的是编写支持多任务并发的应用程序。

进程

进程指的是正在运行的程序,是一系列过程的统称,也是操作系统在调度和进行资源分配的基本单位

进程是实现并发的一种方式

一个程序可以产生多个进程

PID和PPID

PID:系统给进程的编号

PPID:当一个进程a开启了另一个进程b,那么a被称为b的父进程。当pycharm运行了py文件,那么pycharm就是py文件的父进程

并行与并发,阻塞与非阻塞

并发指的是,多个事件同时发生了,需要一直切换完成

并行指的是,多个事件同时进行,互不影响

阻塞状态是因为程序遇到了IO操作,或是sleep,导致后续的代码不能被CPU执行

非阻塞与之相反,表示程序正在被CPU执行。

进程有三种状态,就绪态,运行态,阻塞态

python中实现多进程

python中开启子进程的两种方式

方式1:实例化Process类

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方法

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中的消息,在打印”主“

进程间内存相互隔离

在一个进程内修改了全局变量,其他进程不受影响。就像是运行两个文件,一个修改了,另外一个不受影响。

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函数:

可以让一个进程等待另一个进程结束后再运行

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)
    
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对象常用属性

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已经帮我们自动处理了僵尸进程的回收工作。

猜你喜欢

转载自www.cnblogs.com/zhoajiahao/p/11123086.html