Python学习之协程

协程,又称微线程,纤程。英文名Coroutine.
优点1:协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
优点2:不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲实,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
因为协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。

协程:协作式,非抢占式的程序
A--》B--》A--》C

yield()是协程的关键词
用户态的切换,关键点在于什么时候切换!
协程主要解决的也是IO操作

协程:本质上就是一个线程

协程的优势:1.没有切换的消耗 2.没有锁的概念

 1 #yield的简单实现
 2 import time
 3 import queue
 4 
 5 def consumer(name):
 6 
 7     print("--->ready to eat baozi...")
 8     while True:
 9         new_baozi = yield
10         print("[%s] is eating baozi %s" % (name,new_baozi))
11         #time.sleep(1)
12 
13 def producer():
14 
15     r = con.__next__()
16     r = con2.__next__()
17     n = 0
18     while 1:
19         time.sleep(1)
20         print("\033[32;1m[producer]\033[0m is making baozi %s and %s" %(n,n+1) )
21         con.send(n)
22         con2.send(n+1)
23         n +=2
24 
25 if __name__ == '__main__':
26 
27     con = consumer("c1")
28     con2 = consumer("c2")
29     producer()
30 '''
31 --->ready to eat baozi...
32 --->ready to eat baozi...
33 [producer] is making baozi 0 and 1
34 [c1] is eating baozi 0
35 [c2] is eating baozi 1
36 [producer] is making baozi 2 and 3
37 [c1] is eating baozi 2
38 [c2] is eating baozi 3
39 [producer] is making baozi 4 and 5
40 [c1] is eating baozi 4
41 [c2] is eating baozi 5
42 ......
43 ......
44 '''
#greenlet是一个用C实现的协程模块,相比与python自带的yield,它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator
from greenlet import greenlet

def test1():
    print(12)
    gr2.switch()
    print(34)
def test2():
    print(56)
    gr1.switch()
    print(78)
    gr1.switch()

gr1 = greenlet(test1)
gr2 = greenlet(test2)

gr2.switch()  #切换到test2

'''
56
12
78
34
'''

 

gevent,是一个并发网络库。它的协程是基于greenlet的,并基于libev实现快速事件循环(Linux上是epoll,FreeBSD上是kqueue,Mac OS X上是select)。有了gevent,协程的使用将无比简单,你根本无须像greenlet一样显式的切换,每当一个协程阻塞时,程序将自动调度,gevent处理了所有的底层细节。
# 如下例子,比较串行运行时和利用协程时的执行时间,协程快一些
import gevent
import requests,time
start=time.time()
def f(url):
    print('GET: %s' % url)
    resp =requests.get(url)
    data = resp.text
    print('%d bytes received from %s.' % (len(data), url))

# f('https://www.python.org/')
# f('https://www.yahoo.com/')
# f('https://www.baidu.com/')
# f('https://www.sina.com.cn/')
# f("http://www.xiaohuar.com/hua/")


gevent.joinall([
        gevent.spawn(f, 'https://www.python.org/'),
        gevent.spawn(f, 'https://www.yahoo.com/'),
        gevent.spawn(f, 'https://www.baidu.com/'),
        gevent.spawn(f, 'https://www.sina.com.cn/'),
        gevent.spawn(f, 'http://www.xiaohuar.com/hua/'),
])


print("cost time:",time.time()-start)

'''
GET: https://www.python.org/
49117 bytes received from https://www.python.org/.
GET: https://www.yahoo.com/
482421 bytes received from https://www.yahoo.com/.
GET: https://www.baidu.com/
2443 bytes received from https://www.baidu.com/.
GET: https://www.sina.com.cn/
572837 bytes received from https://www.sina.com.cn/.
GET: http://www.xiaohuar.com/hua/
40320 bytes received from http://www.xiaohuar.com/hua/.
cost time: 2.5858383178710938
'''

 

posted @ 2018-10-09 15:13  一只小妖  阅读(147)  评论(0)    收藏  举报