多进程,进程池,协程

多进程

并行,同时执行。 一个程序运行起来之后,代码用到的资源称之为进程,它是操作系统分配资源的基本单位,不仅可以通过线程完成多任务,进程也是可以的

进程之间是相互独立的

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
原文地址:https://www.cnblogs.com/dayle/p/10028617.html