zoukankan      html  css  js  c++  java
  • 协程技术

    基础概念

    1.定义:纤程,微线程。是为非抢占式多任务产生子程序的计算机组件。协程允许不同入口点在不同位置暂停或开始,简单来说,协程就是可以暂停执行的函数。

    2.协程原理 : 记录一个函数的上下文栈帧,协程调度切换时会将记录的上下文保存,在切换回来时进行调取,恢复原有的执行内容,以便从上一次执行位置继续执行。

    3.协程优缺点

    优点:

    1. 协程完成多任务占用计算资源很少
    2. 由于协程的多任务切换在应用层完成,因此切换开销少
    3. 协程为单线程程序,无需进行共享资源同步互斥处理

    缺点:协程的本质是一个单线程,无法利用计算机多核资源

    标准库协程的实现

    python3.5以后,使用标准库asyncio和async/await 语法来编写并发代码。asyncio库通过对异步IO行为的支持完成python的协程。虽然官方说asyncio是未来的开发方向,但是由于其生态不够丰富,大量的客户端不支持awaitable需要自己去封装,所以在使用上存在缺陷。更多时候只能使用已有的异步库(asyncio等),功能有限。

    第三方协程模

    1.greenlet模块

    安装 : sudo pip3 install greenlet

    函数

    greenlet.greenlet(func)

    • 功能:创建协程对象
    • 参数:协程函数

    g.switch()

    • 功能:选择要执行的协程函数
     1 from greenlet import greenlet
     2 
     3 def test1():
     4   print("执行test1")
     5   gr2.switch()
     6   print("结束test1")
     7   gr2.switch()
     8 
     9 def test2():
    10   print("执行test2")
    11   gr1.switch()
    12   print("结束test2")
    13 
    14 # 将函数变成协程
    15 gr1 = greenlet(test1)
    16 gr2 = greenlet(test2)
    17 gr1.switch()  # 选择执行协程1
    协程运行形态示例

    2.gevent模块

    安装:sudo pip3 install gevent

    函数

    gevent.spawn(func,argv)

    • 功能: 生成协程对象
    • 参数:
      • func 协程函数
      • argv 给协程函数传参(不定参)

    返回值: 协程对象

    gevent.joinall(list,[timeout])

    • 功能: 阻塞等待协程执行完毕
    • 参数:
      • list 协程对象列表
      • timeout 超时时间

    gevent.sleep(sec)

    • 功能: gevent睡眠阻塞
    • 参数:睡眠时间

    gevent协程只有在遇到gevent指定的阻塞行为时才会自动在协程之间进行跳转

    如gevent.joinall(),gevent.sleep()带来的阻塞

     1 import gevent
     2 
     3 
     4 # 协程函数
     5 def foo(a,b):
     6   print("Running foo ...",a,b)
     7   gevent.sleep(2)
     8   print("Foo again")
     9 
    10 def bar():
    11   print("Running bar ...")
    12   gevent.sleep(3)
    13   print("bar again")
    14 
    15 f = gevent.spawn(foo,1,2)
    16 b = gevent.spawn(bar)
    17 
    18 gevent.joinall([f,b]) # 阻塞等待[]中的协成结束
    gevent 协程示例
     1 """
     2 扩展代码
     3 """
     4 
     5 import gevent
     6 from gevent import monkey
     7 monkey.patch_all()  # 在导入socket前执行
     8 from socket import *
     9 
    10 # 处理客户端请求
    11 def handle(c):
    12   while True:
    13     data = c.recv(1024)
    14     if not data:
    15       break
    16     print(data.decode())
    17     c.send(b'OK')
    18   c.close()
    19 
    20 # 创建TCP套接字
    21 s = socket()
    22 s.bind(('0.0.0.0',8888))
    23 s.listen(5)
    24 while True:
    25   c,addr = s.accept()
    26   print("Connect from",addr)
    27   # handle(c)  # 循环方案
    28   gevent.spawn(handle,c)  # 协程方案
    29 
    30 s.close()
    基于协程的tcp并发

    monkey脚本

    作用:在gevent协程中,协程只有遇到gevent指定类型的阻塞才能跳转到其他协程,因此,我们希望将普通的IO阻塞行为转换为可以触发gevent协程跳转的阻塞,以提高执行效率。

    转换方法:gevent 提供了一个脚本程序monkey,可以修改底层解释IO阻塞的行为,将很多普通阻塞转换为gevent阻塞。

    使用方法:

    1.导入monkey

      from gevent import monkey

    2.运行相应的脚本,例如转换socket中所有阻塞

      monkey.patch_socket()

    3. 如果将所有可转换的IO阻塞全部转换则运行all

      monkey.patch_all()

    注意:脚本运行函数需要在对应模块导入前执行

  • 相关阅读:
    四、Ubuntu16.04下TestLink的部署【测试管理必备工具】
    配置反向代理服务器
    三、Ubuntu16.04 安装Jira8.2.2(自带中文包)和破解
    二、Ubuntu16.04安装搜狗wps
    【C#实现漫画算法系列】-判断 2 的乘方
    [Entity Framework+MVC复习总结1]-WebForm与Asp.Net MVC
    【数据结构总结1】-数据结构的自述
    快速理解区块链
    CSS容器属性
    CSS background-clip 属性
  • 原文地址:https://www.cnblogs.com/maplethefox/p/11056047.html
Copyright © 2011-2022 走看看