gevent简明教程

转载于:

进程 线程 协程 异步

并发编程(不是并行)目前有四种方式:多进程、多线程、协程、和异步

  • 多进程编程在python中有类似C的os.fork,更高层封装的有multiprocessing标准库
  • 多线程编程python中有Thread和threading
  • 异步编程在linux下主要有三种实现select、poll、epoll
  • 协程在python中通常会说得yield,关于协程的库主要有greenlet,stackless,eventlet等实现

进程

  • 不共享任何状态
  • 调度由操作系统完成
  • 有独立的内存空间(上下文切换的时候需要保存栈、cpu寄存器、虚拟内存、以及打开的相关句柄等信息,开销大)
  • 通讯主要通过信号传递的方式来实现(实现方式有多种,信号量、管道、事件等,通讯都需要过内核,效率低)

线程

  • 共享变量(解决了通讯麻烦的问题,但是对于变量的访问需要加锁)
  • 调度由操作系统完成(由于共享内存,上下文切换变得高效)
  • 一个进程可以有多个线程,每个线程会共享父进程的资源(创建线程开销占用比进程小很多,可创建的数量也会很多)
  • 通讯除了可使用进程间通讯的方式,还可以通过共享内存的方式进行通信(通过共享内存通信比通过内核要快很多)

协程

  • 调度完全由用户控制
  • 一个线程(进程)可以有多个协程
  • 每个线程(进程)循环按照指定的任务清单顺序完成不同的任务(当任务被堵塞时,执行下一个任务;当恢复时,再回来执行这个任务;任务间切换只需要保存任务的上下文,没有内核的开销,可以不加锁的访问全局变量)
  • 协程需要保证是非堵塞的且没有相互依赖
  • 协程基本上不能同步通讯,多采用异步的消息通讯,效率比较高

总结

  • 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度
  • 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)
  • 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度

聊聊协程
协程,又称线程,纤程
Python的线程并不是标准线程,是系统级进程,线程间上下文切换有开销,而且Python在执行多线程时默认加了一个全局解释器锁(GIL),因此Python的多线程其实是串行的,所以并不能利用多核的优势,也就是说一个进程内的多个线程只能使用一个CPU。

def coroutine(func):
    def ret():
        f = func()
        f.next()
        return f
    return ret

@coroutine
def consumer():
    print "Wait to getting a task"
    while True:
        n = (yield)
        print "Got %s",n

import time
def producer():
    c = consumer()
    task_id = 0
    while True:
        time.sleep(1)
        print "Send a task to consumer" % task_id
        c.send("task %s" % task_id)
if __name__ == "__main__":
    producer()

Wait to getting a task
Send a task 0 to consumer
Got task 0
Send a task 1 to consumer
Got task 1
Send a task 2 to consumer
Got task 2

传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但是容易死锁
如果改用协程,生成者生成消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高

Gevent
介绍
gevent是基于协程的Python网络库。特点:

  • 基于libev的快速事件循环(Linux上epoll,FreeBSD上kqueue)
  • 基于greenlet的轻量级执行单元
  • API的概念和Python标准库一致(如事件,队列)
  • 可以配合socket,ssl模块使用
  • 能够使用标准库和第三方模块创建标准的阻塞套接字(gevent.monkey)
  • 默认通过线程池进行DNS查询,也可通过c-are(通过GEVENT_RESOLVER=ares环境变量开启)
  • TCP/UDP/HTTP服务器
  • 子进程支持(通过gevent.subprocess)
  • 线程池

文章作者: 阿培
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 阿培 !
 上一篇
mysqldump mysqldump
mysqldump -uroot -phonjia@mariadb –single-transaction –master-data=2 –flush-logs -R -E lottery | gzip > /backupmyql/l
2018-08-02
下一篇 
yield关键字 yield关键字
[转载于:]{https://liam0205.me/2017/06/30/understanding-yield-in-python/}yield关键字,及其相关的概念 迭代、可迭代、迭代器迭代(iteration)与可迭代(iterab
2018-07-31
  目录