python_高级进阶(1)进程与并发

进程与并发

进程介绍:

正在进行的一个过程或者说一个任务。而负责执行任务则是cpu

进程的创建(两种方式)


开启进程的第一种方式:
from multiprocessing import Process
import time

def task(name):
    print(f'{name} is running')
    time.sleep(2)
    print(f'{name} is gone')



if __name__ == '__main__':
    # 在windows环境下, 开启进程必须在 __name__ == '__main__' 下面
    p = Process(target=task,args=('SkyRabbit',))  # 创建一个进程对象
    p.start()  # 只是向操作系统发出一个开辟子进程的信号,然后就执行下一行了.
    这个信号操作系统接收到之后,会从内存中开辟一个子进程空间,然后在将主进程所有数据copy加载到子进程,然后在调用cpu去执行.
    开辟子进程开销是很大的.
    print('==主开始')
    time.sleep(3)


    所以永远会先执行主进程的代码.



开启进程的第二种方式:

from multiprocessing import Process
import time

class MyProcess(Process):

    def __init__(self,name):
        super().__init__()
        self.name = name

    def run1(self):
        print(f'{self.name} is running')
        time.sleep(2)
        print(f'{self.name} is gone')


if __name__ == '__main__':
    p = MyProcess('SkyRabbit')
    p.start()
    print('===主')


简单应用:


from multiprocessing import Process
import time
#
def task(name):
    print(f'{name} is running')
    time.sleep(1)
    print(f'{name} is gone')

def task1(name):
    print(f'{name} is running')
    time.sleep(2)
    print(f'{name} is gone')

def task2(name):
    print(f'{name} is running')
    time.sleep(3)
    print(f'{name} is gone')


if __name__ == '__main__':
    # 在windows环境下, 开启进程必须在 __name__ == '__main__' 下面
    # p1 = Process(target=task,args=('SkyRabbit1',))  # 创建一个进程对象
    # p2 = Process(target=task,args=('SkyRabbit2',))  # 创建一个进程对象
    # 一个进程串行的执行三个任务
    start_time = time.time()
    task('SkyRabbit1')
    task1('SkyRabbit2')
    task2('SkyRabbit3')
    print(f'结束时间{time.time() - start_time}')
    三个进程 并发或者并行的执行三个任务
    start_time = time.time()
    p1 = Process(target=task, args=('SkyRabbit1',))  # 创建一个进程对象
    p2 = Process(target=task1, args=('SkyRabbit2',))  # 创建一个进程对象
    p1.start()
    p2.start()
    task2('SkyRabbit3')
    print(f'结束时间{time.time()-start_time}'


获取进程pid


import os
import time
print(f'子进程:{os.getpid()}')
print(f'主(父)进程:{os.getppid()}')
time.sleep(50)



from multiprocessing import Process
import time
import os

def task(name):
    print(f'子进程:{os.getpid()}')
    print(f'主进程:{os.getppid()}')



if __name__ == '__main__':
    p = Process(target=task,args=('SkyRabbit',))  # 创建一个进程对象
    p.start()
    # print('==主开始')
    print(f'====主{os.getpid()}')

验证进程之间的空间隔离


from multiprocessing import Process
import os
import time
name = 'SkyRabbit'

def task():
    global name
    name = 'SkyRabbit_six'
    print(f'子进程{name}')


if __name__ == '__main__':
    p = Process(target=task)  # 创建一个进程对象
    p.start()
    # print('==主开始')
    time.sleep(3)
    print(f'主:{name}')
lst = ['SkyRabbit',]
def task():
    lst.append('SkyRabbit_six')
    print(f'子进程{lst}')
if __name__ == '__main__':
    p = Process(target=task)  # 创建一个进程对象
    p.start()
    # print('==主开始')
    time.sleep(3)
    print(f'主:{lst}')

join让主进程等待子进程结束之后,在执行主进程.



from multiprocessing import Process
import time

def task(name):
    print(f'{name} is running')
    time.sleep(2)
    print(f'{name} is gone')



if __name__ == '__main__':

    p = Process(target=task,args=('SkyRabbit',))  # 创建一个进程对象
    p.start()
    p.join()
    print('==主开始')


# 多个子进程使用join

from multiprocessing import Process
import time

def task(name,sec):
    print(f'{name}is running')
    time.sleep(sec)
    print(f'{name} is gone')


if __name__ == '__main__':
    start_time = time.time()
    p1 = Process(target=task,args=('SkyRabbit_one',1))
    p2 = Process(target=task,args=('SkyRabbit_two',2))
    p3 = Process(target=task,args=('SkyRabbit_three',3))
    p1.start()
    p2.start()
    p3.start()
    print(f'==主{time.time()-start_time}')  # 0.02 这只是主进程结束的时间,与其他进程毫无关系


# 验证1

from multiprocessing import Process
import time

def task(name,sec):
    print(f'{name}is running')
    time.sleep(sec)
    print(f'{name} is gone')


if __name__ == '__main__':
    start_time = time.time()
    p1 = Process(target=task,args=('SkyRabbit',1))
    p2 = Process(target=task,args=('SkyRabbit_two',2))
    p3 = Process(target=task,args=('SkyRabbit_three',3))

    p1.start()
    p2.start()
    p3.start()
    # join 只针对主进程,如果join下面多次join 他是不阻塞的.
    p1.join()
    p2.join()
    p3.join()

    print(f'==主{time.time()-start_time}')

#验证2

from multiprocessing import Process
import time

def task(name,sec):
    print(f'{name}is running')
    time.sleep(sec)
    print(f'{name} is gone')


if __name__ == '__main__':
    start_time = time.time()
    p1 = Process(target=task,args=('SkyRabbit',3))
    p2 = Process(target=task,args=('SkyRabbit_two',2))
    p3 = Process(target=task,args=('SkyRabbit_three',1))

    p1.start()
    p2.start()
    p3.start()
    # join就是阻塞

    p1.join()  # 等2s
    print(f'==主1:{time.time()-start_time}')
    p2.join()
    print(f'===主2:{time.time()-start_time}')
    p3.join()
    print(f'==主3:{time.time()-start_time}')  #


#  优化上面的代码



from multiprocessing import Process
import time

def task(sec):
    print(f'is running')
    time.sleep(sec)
    print(f' is gone')


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()
    # join 只针对主进程,如果join下面多次join 他是不阻塞的.
    p1.join()
    p2.join()
    p3.join()



    #正确示范:
    l1 = []
    for i in range(1, 4):
        p = Process(target=task,args=(i,))
        l1.append(p)
        p.start()

    for i in l1:
        i.join()

    print(f'==主{time.time()-start_time}')

    # join就是阻塞,主进程有join,主进程下面的代码一律不执行,直到进程执行完毕之后,在执行.


守护进程:

古时候 太监守护这个皇帝,如果皇帝驾崩了,太监直接也就死了.
子进程守护着主进程,只要主进程结束,子进程跟着就结束,


if __name__ == '__main__':
    # 在windows环境下, 开启进程必须在 __name__ == '__main__' 下面
    p = Process(target=task,args=('SkyRabbit',))  # 创建一个进程对象
    p.daemon = True  # 将p子进程设置成守护进程,只要主进程结束,守护进程马上结束.
    p.start()
    # p.daemon = True  # 一定要在子进程开启之前设置
    time.sleep(1)
    print('===主')

进程的开启:

一个子进程必须依赖主进程.
一个主进程可以开启多个子进程.
unix: fork创建子进程.
unix(linux,mac): 创建一个子进程会完完全全复制一个主进程所有的资源,初始资源不变.
windows: 操作系统调用CreateProcess 处理进程的创建.
windows:创建一个子进程,会copy主进程所有的资源,但是会改变一些资源.

进程与程序的区别

程序仅仅只是一堆代码,进程是指程序的运行过程.

进程的三种状态:

运行,阻塞,就绪.

并发与并行:

并发:是伪并行,看起来同时运行,实际上就是单个cpu+多道技术,实现并发
并行:同时运行,指具有多个cpu才能实现并行

多道技术概念

空间上的复用: 一个内存可以加载多个进程.

时间上的复用: 当进程遇到IO阻塞,或者长时间运行,操作系统会将此进程挂起,
保留状态,会将cpu强行的切换到另一个进程.

串行:

程序一个一个排队让cpu执行

阻塞:

cpu遇到IO就会阻塞.在原地等着任务结束,
根本不考虑任务是在计算还是在io阻塞,
总之就是一股脑地等任务结束
复制代码

非阻塞:

指在不能立刻得到结果之前也会立刻返回,同时该函数不会阻塞当前线程。

原文地址:https://www.cnblogs.com/SkyRabbit/p/11383866.html