zoukankan      html  css  js  c++  java
  • 使用gevent写异步代码

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

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

    进程

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

    线程

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

    协程

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

    总结

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

    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)
    线程池
    

    import gevent
    from gevent.lock import Semaphore

    sem = Semaphore()
    def f1():
    for item in range(0,10):
    print('f1=>',item)
    gevent.sleep(3)
    def f2():
    for item in range(0,10):
    print('f2
    >',item)
    gevent.sleep(1)
    def f3():
    for item in range(0,10):
    sem.acquire()
    print('f3
    =>',item)
    sem.release()
    def f4():
    for item in range(0,10):
    sem.acquire()
    print('f4>',item)
    sem.release()
    def f5():
    for item in range(0,10):
    sem.acquire()
    print('f5
    =>',item)
    sem.release()
    gevent.sleep(2)
    def f6():
    for item in range(0,10):
    sem.acquire()
    print('f6
    ==>',item)
    sem.release()

    延时操作

    t1 = gevent.spawn(f1)
    t2 = gevent.spawn(f2)

    锁操作

    t3 = gevent.spawn(f3)
    t4 = gevent.spawn(f4)

    延时与锁

    t5 = gevent.spawn(f5)
    t6 = gevent.spawn(f6)
    gevent.joinall([t1,t2,t3,t4,t5,t6])

  • 相关阅读:
    补题列表
    task list
    UVa 11809
    UVA 272 TEX Quotes 题解
    莱州一中2016高考加油视频
    POJ2367-Genealogical tree-拓扑排序
    POJ1094-Sorting It All Out-拓扑排序
    POJ3660-Permutations-传递闭包FLOYD
    POJ3687- Labeling Balls-优先队列拓扑排序
    POJ1201-Intervals- 差分约束
  • 原文地址:https://www.cnblogs.com/lijintian/p/12877246.html
Copyright © 2011-2022 走看看