协程/Coroutine上手

概述

协程/Coroutine(协作的线程?),也可称为微线程,在系统中等级在thread之下(也既一个thread可拥有多个coroutine)(由用户态控制具体实现)(与软件模拟多线程类似)

协程可以看做是一个并行的子程序,有自己的独立栈空间与context,程序可以在主进程中转入某协程中进行操作(主进程挂起),同时在协程中也可以转回主进程(协程挂起,栈空间不销毁),并支持等待之后再回到该协程中进行进一步操作

另一个理解:在使用上等效于一个带token的多进程模型,只有拿到token模型可以进行工作,其余进程必须等待
或者说,”串行同步”
由于同时仍然最多只有一个线程在进行操作,故也无需使用多进程锁

实例

传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁。
如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高:

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)

执行结果:

[PRODUCER] Producing 1…
[CONSUMER] Consuming 1…
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2…
[CONSUMER] Consuming 2…
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3…
[CONSUMER] Consuming 3…
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4…
[CONSUMER] Consuming 4…
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5…
[CONSUMER] Consuming 5…
[PRODUCER] Consumer return: 200 OK

注意到consumer函数是一个generator,把一个consumer传入produce后:
1. 首先调用c.send(None)启动生成器;
2. 然后,一旦生产了东西,通过c.send(n)切换到consumer执行;
3. consumer通过yield拿到消息,处理,又通过yield把结果传回;
4. produce拿到consumer处理的结果,继续生产下一条消息;
5. produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。
Ref:廖雪峰’s blog
可能的局限:由同一个线程同时负责消费和生产,效率显然不够高,同时难以支持更多线程的扩展

项目实例

对于CPP来说,暂时还没有官方支持的协程(可能会于C20加入)

#TODO

协程的优缺点

协程的优点:

(1)无需线程上下文切换的开销,协程避免了无意义的调度(内核负责的调度转变为了线程自己调度,实际上该做的事还得做?/*TODO:去知乎问个问题*/),由此可以提高性能(但也因此,程序员必须自己承担调度的责任,同时,协程也失去了标准线程使用多CPU的能力)

(2)无需原子操作锁定及同步的开销(简化模型)

(3)方便切换控制流,简化编程模型

(4)高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

协程的缺点:

(1)无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。

(2)进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序

Ref:http://www.cnblogs.com/zhangxinqi/p/8337207.html

主要用于异步?//TODO

Coursera machine learning work week3

sigmoid.m

Sigmoid函数是一个信息科学中常用的阀值函数,其意义是将任意离散的值映射到0-1之间以方便进一步处理

新的编辑器真的和狗屎一样,然后我又咕了