码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-09-25 23:30:31      阅读:325      评论:0      收藏:0      [点我收藏+]

标签:无法   class   调用   func   利用   支持   int   用户控制   速度   

一、协程简介、引子

‘‘‘
协程:异步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
‘‘‘

 

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

标签:无法   class   调用   func   利用   支持   int   用户控制   速度   

原文地址:https://www.cnblogs.com/staff/p/9704156.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!