协程介绍前戏协程切换手动协程切换自动

Posted staff

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了协程介绍前戏协程切换手动协程切换自动相关的知识,希望对你有一定的参考价值。

一、协程简介、引子

‘‘‘
协程:异步IO,队列,缓存
nginx效率高就是用了异步IO
协程是一种用户态的轻量级线程。又称微线程,怎么理解呢?后面会说
CPU只认识线程,不会像线程一样吧上下文保存在CPU寄存器,协程是用户控制的。
协程能保留上一次调用时的状态,单线程下实现并发效果
协程的好处:
1、无需线程上下文切换的开销,用yield的时候,只是在函数之间来回切换
2、无需原子操作锁定及同步的开销,没有异步锁之类的东西,因为协程就是单线程
3、方便切换控制流,简化编程模型
4、高并发-高扩展-低成本,一个CPU支持上万个协程都不成问题
缺点:
1、由于是单线程的无法利用多核资源,协程本质上是单线程,
2、协程需要和进程配合才能运行在多CPU上,
3、协程阻塞时会阻塞整个程序
‘‘‘
# 回顾:自己之前写的yield协程,如果生产者里面sleep(1)秒速度变慢,可以理解,看下面
# 假设下面是Nginx,来了3个请求,请求切换应该在读数据库IO的地方切换
import time
def home():
    print("home")
    time.sleep(3)  # 读数据库
    print("home_end")

def bbs():
    print("bbs")
    time.sleep(2)  # 读数据库
    print("bbs_end")

def login():
    print("login")
    time.sleep(1)  # 写数据库
    print("login_end")

‘‘‘
协程之所以能处理大并发,因为遇到IO操作就切换,因为IO耗时
那么什么时候切回去呢??应该是IO完成就切回去。怎么让系统知道IO操作完了呢??
‘‘‘

二、协程切换手动挡

‘‘‘
需要安装gevent
ps:gevent是自动挡,由于自动挡封装了手动挡
   安装gevent之后,就自动有greenlet
greenlet是手动切换
‘‘‘
from greenlet import greenlet

def test1():
    print(12)
    gr2.switch()
    print(34)
    gr2.switch()

def test2():
    print(56)
    gr1.switch()
    print(78)

gr1 = greenlet(test1)  # 启动一个协程
gr2 = greenlet(test2)
gr1.switch()     # 类似于yield语句

‘‘‘
12
56
34
78
‘‘‘

 

三、协程切换自动挡

import gevent
‘‘‘
如果是time.sleep()就变成串行的了
‘‘‘

def foo():
    print("foo_begin")
    gevent.sleep(2)
    print("foo_end")
def bar():
    print("bar_begin")
    gevent.sleep(1)
    print("bar_end")
def func():
    print("func_begin")
    gevent.sleep(0)
    print("func_end")
gevent.joinall([gevent.spawn(foo),
                gevent.spawn(bar),
                gevent.spawn(func)])
‘‘‘
foo_begin
bar_begin
func_begin
func_end
bar_end
foo_end
‘‘‘

 

以上是关于协程介绍前戏协程切换手动协程切换自动的主要内容,如果未能解决你的问题,请参考以下文章

并发编程之协程

python:协程的介绍

greenlet 实现手动协程切换

Kotlin协程到底是怎么切换线程的?你是否知晓?

Python知识点-协程

协程:gevent模块,遇到i/o自动切换任务 038