python学习日志0228 协程

本文介绍了Python中的协程概念,强调其作为微线程和最小运行单位的特点,及其在高并发场景下的优点。协程能减少上下文切换和同步开销,但无法充分利用多核资源。文章提到了greenlet和gevent等实现协程的方法,并讨论了事件驱动编程在服务器处理请求中的应用。

1.协程:又称微线程,纤程,可根据程序自身需要自己进行调度。

(1)在一个线程中会有很多函数(子程序),在子程序执行过程中可以中断去执行别的子程序,而别的子程序也可以中断回来继续执行之前的子程序,这个过程就称为协程。 同一线程内一段代码在执行过程中会中断然后跳转执行别的代码,接着在之前中断的地方继续开始执行

(2)进程>线程>协程  协程为系统最小运行单位 

2.协程的优点:

(1)无需线程上下文切换的开销,协程避免了无意义的调度,由此可以提高性能(但也因此,程序员必须自己承担调度的责任,同时,协程也失去了标准线程使用多CPU的能力)

(2)无需原子操作锁定及同步的开销

(3)方便切换控制流,简化编程模型

(4)高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

3.协程的缺点:

(1)无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上

(2)进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序

 4.协程的实现(三种方式)

方式1 

def consumer(name):
    print('开始吃包子...')
    while True:
        print('\033[31;1m[consumer]%s需要包子\033[0m'%name)
        bone = yield   #接收send发送的数据
        print('\033[31;1m[%s]吃了%s个包子\033[0m'%(name,bone))
def producer(obj1):
    obj1.send(None)   #必须先发送None
    for i in range(3):
        print('\033[32;1m[producer]\033[0m正在做%s个包子'%i)
        obj1.send(i)


if __name__ == '__main__':
    con1 = consumer('消费者A')  #创建消费者对象
    producer(con1)

方式2  greenlet模块实现协程 

import greenlet
def A():
    print('a.....')
    g2.switch()  #切换至B
    print('a....2')
    g2.switch()
def B():
    print('b.....')
    g1.switch()  #切换至A
    g3.switch()
    print('b....2')

def C():
    print("c......")
    g2.switch()
g1 = greenlet.greenlet(A) #创建一个线程
g2 = greenlet.greenlet(B)
g3 = greenlet.greenlet(C)
g1.switch()

 方式3  gevent模块实现协程

原理:gevent会主动识别程序内部的IO操作,当子程序遇到IO后,切换到别的子程序。如果所有的子程序都进入IO 

import gevent
from gevent.event import Event
evt = Event()
def setter():
    print('A: Hey wait for me, I have to do something')
    gevent.sleep(3)
    print("Ok, I'm done")
    evt.set()
def waiter():
    print("I'll wait for you")
    evt.wait()  # blocking
    print("It's about time")

def main():
    gevent.joinall([
        gevent.spawn(setter),
        gevent.spawn(waiter),
        gevent.spawn(waiter),
    ])
if __name__ == '__main__': main()

5.事件驱动编程:一种编程规则 

服务器处理模型的程序时,有以下几种模型:

(1)每收到一个请求,创建一个新的进程,来处理该请求;

优缺点:实现简单,但开销较大,导致服务器性能较差

(2)每收到一个请求,创建一个新的线程,来处理该请求;

优缺点:多线程在同一进程中运行,可能产生死锁问题 

(3)每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求(大多数网络服务器采用的方式)

优缺点:代码逻辑复杂,占用内存空间小,数据安全。 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值