协程与线程

协程与IO

协程的出现出现为克服同步模型和异步模型的缺点,并结合他们的优点提供了可能: 现在假设我们有3个协程A,B,C分别要进行数次IO操作。

这3个协程运行在同一个调度器或者说线程的上下文中,并依次使用CPU。调度器在其内部维护了一个多路复用器(epoll/select/poll)。

  1. 协程A首先运行,当它执行到一个IO操作,但该IO操作并没有立即就绪时,A将该IO事件注册到调度器中,并主动放弃CPU。
  2. 这时调度器将B切换到CPU上开始执行,同样,当它碰到一个IO操作的时候将IO事件注册到调度器中,并主动放弃CPU。
  3. 调度器将C切换到cpu上开始执行。
  4. 当所有协程都被“阻塞”后,调度器检查注册的IO事件是否发生或就绪。**假设此时协程B注册的IO时间已经就绪,调度器将恢复B的执行,B将从上次放弃CPU的地方接着向下运行。**A和C同理。

这样,对于每一个协程来说,它是同步的模型;但是对于整个应用程序来说,它是异步的模型。

进程 协程 线程

  • 多核CPU,CPU密集型应用
    此时多线程的效率是最高的,多线程可以使到全部CPU核心满载,又避免了协程间切换造成性能损失。当CPU密集型任务时,CPU一直在利用着,切换反而会造成性能损失,即便协程上下文切换消耗最小,但也还是有消耗的。

  • 多核CPU,IO密集型应用
    此时采用多线程多协程效率最高,多线程可以使到全部CPU核心满载,而一个线程多协程,则更好的提高了CPU的利用率。

  • 单核CPU,CPU密集型应用
    单进程效率是最高,此时单个进程已经使到CPU满载了。

  • 单核CPU,IO密集型应用
    多协程,效率最高。例如,看了上面应该也是知道的了

例子

传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁。

如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高:

1.用多线程的思路

import threading, time
import Queue    #导入消息队列模块
import random   #导入随机数模块,是为了模拟生产者与消费者速度不一致的情形
q = Queue.Queue()    #实例化一个对象

def Producer(name):          #生产者函数
    for i in range(20):  
        q.put(i)     #将结果放入消息队列中
        print '\033[32;1mProducer %s has made %s baozi....\033[0m' % (name, i)
        time.sleep(random.randrange(3))    #生产者的生产速度,3s内
def Consumer(name):          #消费者函数
    count = 0
    while count < 20:
        data = q.get()    #取用消息队列中存放的结果
        print '\033[31;1mConsumer %s has eatem %s baozi...chihuo...\033[0m' % (name, data)
        count += 1
        time.sleep(random.randrange(4))    #消费者的消费速度,4s内

p = threading.Thread(target = Producer, args = ('Alex',))
c = threading.Thread(target = Consumer, args = ('Wangfanhao',))

p.start()
c.start()

2.用协程的思路

def consumer():
    r = ''
    while True:
        n = yield r
        if not n:
            return
        print('[CONSUMER] Consuming %s...' % n)
        r = '200 OK'

def produce(c):
    c.send(None)
    n = 0
    while n < 5:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        r = c.send(n)
        print('[PRODUCER] Consumer return: %s' % r)
    c.close()

c = consumer()
produce(c)

猜你喜欢

转载自blog.csdn.net/jason_cuijiahui/article/details/82587076
今日推荐