博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python 之协程
阅读量:6592 次
发布时间:2019-06-24

本文共 2506 字,大约阅读时间需要 8 分钟。

  • 协程,又称微线程,协程是一种用户态的轻量级线程。
  • 协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前
    保存的寄存器上下文和栈。因此,协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,
    就相当于进入上一次调用的状态,换种说法:进入上一次离开时,所处逻辑流的位置。
  • 协程的好处:
    • 无需线程上下文切换的开销;
    • 无需原子操作锁定及同步的开销;
    • 方便切换控制流,简化编程模型;
    • 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题,所以很适合用于高并发处理。
  • 缺点:
    • 无法利用多核资源:协程的本质是单个线程,它不能同时将单个CPU的多个核用上,协程需要和进程配合才能运行在多
      CPU上,当然我们日常所编写的绝大部分应用都没有这个必要,除非是CPU密集型应用;
    • 进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序;
# 示例: yield 支持下的协程import timeimport queuedef consumer(name):    print('--- 开始吃包子---')    while True:        new_baozi = yield        print('[%s] 正在吃包子 %s' % (name, new_baozi))def producer():    r = con.__next__()    r = con2.__next__()    n = 0    while n < 5:        n += 1        con.send(n)        con2.send(n)        print('\033[32;1m[producer]\033[0m 正在做包子 %s' % n)if __name__ == '__main__':    con = consumer('c1')        # 创建一个生成器对象 con    con2 = consumer('c2')       # 创建另一个生成器对象 con2    p = producer()# 示例二: greenlet 下的协程from greenlet import greenletdef test1():    print('12')    gr2.switch()    print('34')    gr2.switch()def test2():    print('56')    gr1.switch()    print('78')gr1 = greenlet(test1)# print(gr1)        # 
gr2 = greenlet(test2)gr1.switch()# 示例三: gevent 下的协程# Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet,# 它是以C扩展模块形式接入Python的轻量级协程。import geventdef foo(): print('Running in foo') gevent.sleep(1) print('Explicit context switch to foo again.')def bar(): print('Explicit context to bar') gevent.sleep(1) print('Implicit context switch back to bar.')gevent.joinall([ gevent.spawn(foo), gevent.spawn(bar),])# 示例四: 通过 gevent 实现单线程下的多 socket 并发# server 端import geventfrom gevent import socketdef server(port): s = socket.socket() s.bind(('0.0.0.0', port)) s.listen(500) while True: cli, addr = s.accept() gevent.spawn(handle_request, cli)def handle_request(conn): try: while True: data = conn.recv(1024) print('recv:', data) conn.send(data) if not data: conn.shutdown(socket.SHUT_WR) except Exception as ex: print(ex) finally: conn.close()if __name__ == '__main__': server(8001)# client 端import socketHOST = 'localhost'PORT = 8001s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect((HOST, PORT))while True: msg = bytes(input('>>>:'), encoding = 'utf8') s.sendall(msg) data = s.recv(1024) print('Received', repr(data))s.close()

参考资料:

转载于:https://www.cnblogs.com/linkworld/p/8660246.html

你可能感兴趣的文章
去掉VS2012中的红色波浪下划线
查看>>
[文档]关于接口文档的写法
查看>>
一次tensorflow的尝试
查看>>
建立Git版本库管理框架例子
查看>>
nginx防止部分DDOS攻击
查看>>
编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 但是要保证汉字......
查看>>
number_format() 函数定义和用法
查看>>
Java8中聚合操作collect、reduce方法详解
查看>>
查看记录
查看>>
mybatis报ORA-00911: 无效字符
查看>>
Swift UIView动画animateWithDuration
查看>>
Maven 集成Tomcat插件
查看>>
css中的line-height问题
查看>>
nagios监控配置
查看>>
我的友情链接
查看>>
Linux运维学习笔记之二:常用命令1
查看>>
snort安装常见问题及解决方法
查看>>
在ubuntu系统安装jdk
查看>>
很久没写了
查看>>
我的友情链接
查看>>