协程(Python)

目录

1、协程的优势:

2、生产者消费者协程模型

3、协程gevent实例


1、协程的优势:

  • 协程的执行效率高。因为子程序切换不是线程切换,而是由程序自身控制。因此,没有线程切换的开销,和多线程相比,线程数量越多,相同数量的协程体现出的优势越明显
  • 不需要多线程的锁机制。由于只有一个线程,也不存在同时写变量的冲突,在协程中控制共享资源不需要加锁,只需要判断数据的状态,所以执行效率远高于线程 ,对于多核CPU可以使用多进程+协程来尽可能高效率地利用CPU。
  • 通俗易懂的回答:让原来要使用异步+回调方式写的非人类代码,可以用看似同步的方式写出来...

2、生产者消费者协程模型

 (1)yield方式

import time
 
def consumer():
    r = ''
    while True:
        n = yield r
        if not n:
            return
 
        print('[消费者] <--- Consuming %s...' % n)
        time.sleep(1)
        r = 'ok'
 
def producer(c):
    next(c)
    n = 0
    while n < 5:
        n = n + 1
        print('[生产者] ---> Producing %s...' % n)
        # 和next有同样的同能,可以触发函数到下一个yield,
        # 区别于next的是可以像yield的左边的变量传值,例如上面yield左边的n
        c_ret = c.send(n)  
 
        print('[生产者] Consumer return %s' % c_ret)
    c.close()
 
 
if __name__ == '__main__':
    c = consumer()
    producer(c)

结果如下:

[生产者] ---> Producing 1...
[消费者] <--- Consuming 1...
[生产者] Consumer return ok
[生产者] ---> Producing 2...
[消费者] <--- Consuming 2...
[生产者] Consumer return ok
[生产者] ---> Producing 3...
[消费者] <--- Consuming 3...
[生产者] Consumer return ok
[生产者] ---> Producing 4...
[消费者] <--- Consuming 4...
[生产者] Consumer return ok
[生产者] ---> Producing 5...
[消费者] <--- Consuming 5...
[生产者] Consumer return ok

   使用yield手动实现协程是比较麻烦的,Python提供了greenlet和gevent模块用来实现协程。

(2)greenlet方式

from greenlet import greenlet
import time
 
def A():
    while 1:
        print('-------A-------')
        time.sleep(0.5)
        g2.switch()
 
def B():
    while 1:
        print('-------B-------')
        time.sleep(0.5)
        g1.switch()
 
g1 = greenlet(A)  #创建协程g1
g2 = greenlet(B)
 
g1.switch()  #跳转至协程g1

结果如下:

-------A-------
-------B-------
-------A-------
-------B-------
-------A-------

(3)gevent方式

         gevent每次遇到io操作,需要耗时等待时,会自动跳到下一个协程继续执行。

import gevent
 
def A():
    while 1:
        print('-------A-------')
        gevent.sleep(1) #用来模拟一个耗时操作,注意不是time模块中的sleep
 
def B():
    while 1:
        print('-------B-------')
        gevent.sleep(0.5)  #每当碰到耗时操作,会自动跳转至其他协程
 
g1 = gevent.spawn(A) # 创建一个协程
g2 = gevent.spawn(B)
g1.join()  #等待协程执行结束
g2.join()

结果如下:

-------A-------
-------B-------
-------B-------
-------A-------
-------B-------
-------B-------
-------A-------
-------B-------
-------B-------

3、协程gevent实例

      利用gevent完成协程方式的回显服务器


import gevent
from gevent import monkey,socket
 
monkey.patch_all()   #有IO才做时需要这一句
 
s = socket.socket(2,1)  #用的都是gevent模块中的socket,但用法一样
s.setsockopt(1,2,1)
s.bind(('',8080))
s.listen(1024)
 
def func_accept():
    while 1:
        cs,userinfo = s.accept()
        print('来了一个客户'+str(userinfo))
        g = gevent.spawn(func_recv,cs)  #每当有用户连接,增加一条协程
 
def func_recv(cs):
    while 1:
        recv_data = cs.recv(1024)
        print(recv_data)  #程谁堵塞了,便会跳转至其他协程
        if len(recv_data) > 0:
            cs.send(recv_data)
        else:
            cs.close()
            break
 
g1 = gevent.spawn(func_accept)
g1.join()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值