多进程
并行,同时执行。 一个程序运行起来之后,代码用到的资源称之为进程,它是操作系统分配资源的基本单位,不仅可以通过线程完成多任务,进程也是可以的
进程之间是相互独立的
cpu计算密集的时候适合用多进程
有几核CPU就可以同时执行几个进程
开启进程需要调用 multiprocessing 模块
import multiprocessing #调用进程模块
import time
def test1():
for i in range(5):
time.sleep(1)
print('test', i)
def test2():
for i in range(5):
time.sleep(1)
print('test', i)
if __name__ == '__main__': #固定格式(必须加)后面的执行代码要缩进
p1 = multiprocessing.Process(target=test1) #添加一个test1变成一个子进程赋值给p1
p2 = multiprocessing.Process(target=test2)
p1.start() #开启p1子进程
p2.start()
结果:
#停顿一秒
test 0
test 0
#停顿一秒
test 1
test 1
#停顿一秒
test 2
test 2
#停顿一秒
test 3
test 3
#停顿一秒
test 4
test 4
进程之间不共享,相互独立
import multiprocessing
g_num = 0
def edit():
global g_num
for i in range(10):
g_num += 1
print(g_num)
def reader():
print(' ')
print(g_num)
if __name__ == '__main__':
p1 = multiprocessing.Process(target=edit)
p2 = multiprocessing.Process(target=reader())
p1.start()
p2.start()
print(g_num)
结果:
全局变量没有被改变
0
0
10
进程池的并发
apply_async 是异步非阻塞的。即不用等待当前进程执行完毕,随时根据系统调度来进行进程切换。首先主进程开始运行,碰到子进程后,主进程仍可以先运行,等到操作系统进行进程切换的时候,在交给子进程运行。可以做到不等待子进程执行完毕,主进程就已经执行完毕,并退出程序。
import multiprocessing #调用进程模块 from multiprocessing import Pool #调用进程池模块 import time import threading g_num = 0 def test1(): for i in range(10): time.sleep(1) print('test1', i) def test2(): for i in range(10): time.sleep(1) print('test2', i) def test3(): for i in range(10): time.sleep(1) print('test3', i) if __name__ == '__main__': pool = Pool() #括号里写几就代表可以允许同时执行几个进程,不写的话就按照cpu的各项指标系统分配同时执行的进程数。 pool.apply_async(test1) ##维持执行的进程,当一个进程执行完毕后会添加新的进程进去 pool.apply_async(test2) pool.apply_async(test3) pool.close() #关闭进程池,表示不能再往进程池中添加进程,需要在join之前调用 pool.join() #等待进程池中的所有进程执行完毕
进程包括线程(线程是轻量级的)
线程包括协程(协程是微量级的)
协程比线程更加适合IO密集的操作
协程
协程,又称微线程,纤程。英文名Coroutine。 首先我们得知道协程是啥?协程其实可以认为是比线程更小的执行单元。 为啥说他是一个执行单元,因为他自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。
那么这个过程看起来和线程差不多。其实不然, 线程切换从系统层面远不止保存和恢复 CPU上下文这么简单。 操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。 所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。
需要调用 gevent 模块,第三方模块,需要pip下载。
import gevent,time from gevent import monkey monkey.patch_all() def test1(): for i in range(10): time.sleep(1) print('1===>', i) def test2(): for i in range(10): time.sleep(2) print('2===>', i) g1 = gevent.spawn(test1) g2 = gevent.spawn(test2) g1.join() g2.join()
因为第一个协程挺一秒,第二个协程停2秒,所以CPU一个时间段内执行两次协程1,一次协程2
1===> 0 2===> 0 1===> 1 1===> 2 2===> 1 1===> 3 1===> 4 2===> 2 2===> 3 2===> 4