简介
- 进程:资源调度的基本单位,亦是一个程序在一个数据集上的一次动态执行过程,如下每一个应用程序即一个进程。同时一个主进程下,可能会有多个子进程。
并发与并行
进程就像工厂(即CPU核心数,一般为8核,4核等),为程序进行工作,当工厂数量很多的时候,可以一个工厂做一个程序的工作,称之为并行。
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1325594/1594259389438-6a315984-bbb1-4329-a969-be3a7043ffa5.png#align=left&display=inline&height=159&margin=%5Bobject%20Object%5D&name=image.png&originHeight=338&originWidth=548&size=33754&status=done&style=none&width=257)
如果CPU是单核,但是想要同时运行多个应用,就需要再两个程序间切换,只是切换的速度特别快,人眼一般体会不到,这就称之为并发。
普通多函数
import multiprocessing
import time
def func1():
while True:
print("running func1")
time.sleep(1)
def func2():
while True:
print("running func2")
time.sleep(1)
if __name__ == '__main__':
func1()
func2()
- 运行结果:
- 如上可知,程序一直执行func1,造成阻塞。不会运行func2,如果想要func1和func2同时运行,可以使用多进程。
阻塞与非阻塞
创建子进程
- p = multiprocessing.Process(target=func1, args=())
- 开启进程
- p.start()
- 查看进程
- os.getpid()
- 等待子进程结束 timeout 等待超时
- p.join(timeout=5)
- 关闭进程
- p.close()
- 守护进程 再主进程结束后结束子进程
- p.daemon = True
import multiprocessing
import time
import os
def func1():
print("当前进程:", os.getpid())
for i in range(3):
print("running func1")
time.sleep(1)
def func2():
print("当前进程:", os.getpid())
for i in range(3):
print("running func2")
time.sleep(1)
if __name__ == '__main__':
p = multiprocessing.Process(target=func1, args=())
p1 = multiprocessing.Process(target=func2, args=())
# p.daemon = True
# p1.daemon = True
print("主进程:", os.getpid())
p.start()
p1.start()
p.join()
p1.join()
p.close()
p1.close()
print("程序结束!")
- 运行结果:
- 由上图可知,主进程先执行,然后使用start开启子进程,主进程等待子进程结束之后再结束!
- 如果使用了daemon的话,主进程不等待子进程运行完,就结束主进程
继承方式
import multiprocessing
import time
import os
class P1(multiprocessing.Process):
def run(self):
print("当前进程:", os.getpid())
for i in range(3):
print("running func1")
time.sleep(1)
class P2(multiprocessing.Process):
def run(self):
print("当前进程:", os.getpid())
for i in range(3):
print("running func2")
time.sleep(1)
if __name__ == '__main__':
p1 = P1()
p2 = P2()
p1.daemon = True
p2.daemon = True
p1.start()
p2.start()
print("主进程:", os.getpid())
time.sleep(2)
print("程序结束!")
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1325594/1594262132516-14353069-b26f-4af2-be92-73d314ae123b.png#align=left&display=inline&height=172&margin=%5Bobject%20Object%5D&name=image.png&originHeight=215&originWidth=715&size=46179&status=done&style=none&width=573)
如上所示,使用了守护进程,在子进程还未结束的时候,主进程执行结束后即程序结束。主要守护进程需要在进程开启前使用
使用进程池
实例化
- pool = multiprocessing.Pool()
- 向进程池添加任务异步执行
- pool.apply_asnyc(func=func, args=())
- 关闭进程池 不能继续添加任务
- pool.close()
- 主进程等待子进程结束
- pool.join()
import multiprocessing
import time
import os
def func1(num):
print("当前进程:", os.getpid())
for i in range(num):
print(f"running func1 {num}")
time.sleep(1)
def func2(num):
print("当前进程:", os.getpid())
for i in range(num):
print(f"running func2 {num}")
time.sleep(1)
if __name__ == '__main__':
pool = multiprocessing.Pool(1)
pool.apply_async(func=func1, args=(1,))
pool.apply_async(func=func2, args=(2,))
pool.close()
pool.join()
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1325594/1594263244287-8a17b2d8-39f9-4025-839c-550518510196.png#align=left&display=inline&height=153&margin=%5Bobject%20Object%5D&name=image.png&originHeight=186&originWidth=697&size=50228&status=done&style=none&width=573)
- 需要注意参数元组传递方式
进程间通信
- 进程与进程之间相互独立,资源不共享。进程与进程之间传递信息,可以使用队列,类似于列表可以存放数据,不过是先进先出。
- 导包
- from multiprocessing import Queue
- 实例化
- q = Queue()
- 常用方法
- q.put() 向队列添加一个数据 如果队列满了则阻塞
- q.get() 从队列中取出一个数据 如果队列为空则阻塞
- q.qsize() 查看队列大小
- q.empty() 判断队列是否为空
- q.put_nowait() 添加一个数据,如果队列满了则报错
- q.get_nowait() 获取一个数据,如果队列为空则报错 ```python from multiprocessing import Queue import multiprocessing import time import os
- 导包
def func1(q): print(“当前进程:”, os.getpid())
for i in range(3):
q.put(i)
print(f"running func1 put {i}")
time.sleep(1)
def func2(q): time.sleep(1) print(“当前进程:”, os.getpid())
while q.qsize():
n = q.get()
print(f"running func2 get {n}")
time.sleep(1)
if name == ‘main‘: q = Queue()
p = multiprocessing.Process(target=func1, args=(q,))
p1 = multiprocessing.Process(target=func2, args=(q, ))
print("主进程:", os.getpid())
p.start()
p1.start()
p.join()
p1.join()
p.close()
p1.close()
print("程序结束!")
```
运行结果
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1325594/1594264749245-d54e3634-3fd6-4448-ab10-5054ec61b14f.png#align=left&display=inline&height=108&margin=%5Bobject%20Object%5D&name=image.png&originHeight=244&originWidth=1291&size=55547&status=done&style=none&width=573)
进程之间虽然不共享资源 ,但是共享一套文件系统,比如对同一文件进行写入的时候,必然带来竞争导致错乱,需要对进程进行控制,需要用到进程锁
- 使用:
- 导包
- from multiprocssing import Lock
- 进程池导包方式
- from multiprocssing.Manager() import Lock
- 实例化
- mutex = Lock()
- 方法
- mutex.aquire() 锁定
- mutex。release() 释放
- 导包