最近在学习stackless python , 对进程,线程, 协程等有了一些新的认识.

首先这些东西都是为了”并发“, 也就是”同一时间“执行多个任务.  不过这三者在实现这一目标上有不同的方法. 

首先三者都构成任务(Task), 都有下面一些特征.

  • 独立的控制流
  • 有内部状态
  • 可以被调度
  • 可以同其他任务通讯 

进程之间不共享任何状态,  进程的调度由操作系统完成, 进程间通讯也要通过操作系统. (共享内存, 管道等等).

进程的问题: 进程间切换开销很大, 通讯麻烦. 

线程之间共享变量, 解决了通讯麻烦的问题, 但是对于变量的访问需要锁.  线程的调度主要也是有操作系统完成, 但用户程序自己有可以有一些控制(比如将自己挂起等). 线程间的切换开销比进程小了很多。

协程的调度完全由用户控制,协程间的切换开销很小, 可以不加锁的访问全局变量. 

一个进程可以有多个线程, 一个线程可以有多个协程. 

有这样一个说法,  

关于操作系统线程的一般常识是:(1)尽量不要使用它,(2)如果非用不可,就能少用一点就少用一点。而stackless的微线程则使我们从这些限制中解放出来。

这种说法未必完全正确, 但是在实际的情况中确实是使用线程要很小心, 对于共享的变量的访问要小心翼翼的加锁, 同时又要避免死锁.   怎样安全的结束一个线程有时候也是比较麻烦的…

为什么要加锁? 因为线程的调度是操作系统完成的, 你无法控制它. 它可能在你不希望的时候中断你的程序. 比如

thread1:
    1: a = [1,2]
    2: print a[1]

    thread2:
    3: a[1] = 3
    4: del a[1]
    5: print a

上面的代码就不是线程安全的.  执行序列可能是 1,3,4,2,5  或者 其他很多组合.    (例子不太好…)

当我们使用协程的时候我们自己控制控制流程.

thread1:
    a = [1,2]
    yield
    print a[1]

    thread2:
    a[1] = 3
    yield
    del a[1]
    print a

 

参考资料:

1. A Curious Course on Coroutines and Concurrency 强烈推荐 

2. http://zh.wikipedia.org/wiki/协程

3. Stackless Python 并发式编程介绍

4. eurasia 基于国产高性能Python Web 框架   (该项目的邮件列表有一些高质量的关于stackless python 的讨论)

 

下面一篇预告:
stackless python  中 tasklet 调度的使用心得