zoukankan      html  css  js  c++  java
  • 并发编程之协程

    协程介绍

    协程:是单线程下的并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程: 协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。

    1. python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)

    2. 单线程内开启协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(非io操作的切换与效率无关)

    对比操作系统控制线程的切换,用户在单线程内控制协程的切换

    优点:

    1. 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级

    2. 单线程内就可以实现并发的效果,最大限度地利用cpu

    缺点:

    1. 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程

    2. 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程

    gevent模块

    Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。

    gevent模块本身无法检测常见的一些io操作, 在使用的时候需要你额外导入一句话。即导入猴子补丁

    import time
    from gevent import spawn
    from gevent import monkey
    """
    gevent模块本身无法检测常见的一些io操作, 在使用的时候需要你额外导入一句话
    from gevent import monkey
    monkey.patch_all()
    
    """
    monkey.patch_all()
    
    
    def heng():
        print('')
        time.sleep(2)
        print('')
    
    
    def ha():
        print('')
        time.sleep(3)
        print('')
    
    
    if __name__ == '__main__':
        start_time = time.time()
        g1 = spawn(heng)
        g2 = spawn(ha)
        g1.join()
        g2.join()  # 等待被检测的任务执行完毕, 在往后继续执行
        print(time.time() - start_time)  # 3.0037176609039307

    由于上面的两句话在使用gevent模块的时候是肯定要导入的, 所以还支持简写

    from gevent import monkey; monkey.patch_all()

     

    基于协程实现TCP服务并发

    from gevent import spawn
    from gevent import monkey;
    
    monkey.patch_all()
    import socket
    
    
    def communication(conn):
        while True:
            try:
                data = conn.recv(1024)
                if len(data) == 0: break
                conn.send(data.upper())
            except Exception as e:
                print(e)
    
        conn.close()
    
    
    def server(ip, port):
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server.bind((ip, port))
        server.listen()
    
        while True:
            conn, addr = server.accept()
            spawn(communication, conn)
    
    
    if __name__ == '__main__':
        g1 = spawn(server, '127.0.0.1', 8080)
        g1.join()
  • 相关阅读:
    awk 连接字符串
    VCF (Variant Call Format)格式详解
    Extracting info from VCF files
    JAVA中AES对称加密和解密
    关于Java中常用加密/解密方法的实现
    Java的MD5加密和解密
    java实现MD5加密
    Java中String和byte[]间的转换浅析
    Java中字符串和byte数组之间的相互转换
    字符串与byte[]之间的转换
  • 原文地址:https://www.cnblogs.com/featherwit/p/13391945.html
Copyright © 2011-2022 走看看