进程与并发
进程介绍:
正在进行的一个过程或者说一个任务。而负责执行任务则是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阻塞,
总之就是一股脑地等任务结束
复制代码
非阻塞:
指在不能立刻得到结果之前也会立刻返回,同时该函数不会阻塞当前线程。