协程

一、什么事协程?

  协程是一个比线程更加轻量级的单位,是组成线程的各个函数。

  携程本身没有实体

二、为什么要有协程?

  1、为了在单线程内实现并发的效果。

  因为Cpython中有一个GIL锁,限制了同一时间点,只能执行一个线程所以想要在执行

  一个线程的期间充分利用CPU的性能。

  2、并发的本质是什么?

  并发就是要交替执行,即:切换 (函数1阻塞就去执行函数2)+ 保存状态(从函数1切换到函数2时依然保存着函数1的状态)

  3、cpu为什么要进行切换?

  1)因为某个程序阻塞了

  2)因为某个时间片用完了

  因此,当程序阻塞的时候,为了提高cpu的利用率,就需要在进行IO操作的时候立即切换到其他程序去执行。

三、实现程序切换的方法

  greenlet模块:能够实现简单的程序切换,但是无法做到,在IO操作时自动切换

  代码:

  

from greenlet import greenlet
import time


def play_basketball(name):
    print('%s一记大帽' % name)
    time.sleep(1)
    a2.switch('艾弗森')
    print('%s一记劈扣' % name)
    time.sleep(1)
    a2.switch()


def swimming(name):
    print('%s 在蛙泳' % name)
    time.sleep(1)
    a1.switch()
    print('%s 竟然还会蝶泳' % name)


a1 = greenlet(play_basketball)
a2 = greenlet(swimming)

a1.switch('勒布朗')
greenlet模块实现切换

  gevent模块:可以实现在某函数内部遇到IO操作时,自动切换到其他函数,大大提高了

cpu的利用率。

  g = gevent.spawn(func, 参数) 注册一下函数func,返回一个对象g。

  gevent.join(g)  等待g指向的函数func执行完毕后,如果在执行过程中遇到IO操作就切换。

  gevent.joinall([g1,g2,g3])  等待[g1,g2,g3]指向的函数func执行完毕

  代码:

  gevent 只能识别自己的IO操作,不能识别其他的IO操作,

  举个列子:遇到gevent.sleep()  就会切换     遇到time.sleep()就不会切换

  为了解决这种情况,引入了monkey

  from gevent import monkey

  gevent.patch_all

from gevent import monkey
import gevent
import time

monkey.patch_all()
lst = []


def fn(i):
    time.sleep(1)
    print(i)


start_time = time.time()
for i in range(10):
    g = gevent.spawn(fn, i)
    lst.append(g)
gevent.joinall(lst)
print(time.time() - start_time)
gevent(自动切换)

 

原文地址:https://www.cnblogs.com/wf123/p/9551041.html