“有了协程框架再也不用关注线程池调度问题”,在阿里双十一电子书《不一样的技术创新》中看到这样一句话。看到这句话的时候,内心活动是这样的——当我们还在玩线程池的时候,阿里的爸爸们已经在研究调度问题并有解决方案了。所以保持对这句话的质疑和思考,有了今天的整理和学习,为进一步学习协程框架,如Akka起一个头。
并发和并行
在多线程编程中,并发(Concurrency)和并行(Parallelism)这两个概念时常会被提到,但是这两个概念却不是一个意思。
并发(Concurrency)
并发指的是应用程序同时处理多个任务,多个任务都能同时取得进展。
比如吃饭的时候,电话来了,停下手和嘴去接电话,打完电话继续吃饭,这叫并发。
并行(Parallelism)
并行指的是应用可以将任务拆成更小的子任务,而这些子任务可以同时平行着被处理。
比如吃饭的同时,我还能打电话,这就是并行。
对比
由上面可以看出,并发依赖于应用如何处理多任务。应用同时只能处理一个任务,处理完在进行下一个任务,这叫顺序地(Sequentially)执行;如果应用同时能处理多个任务,这就叫并发地。
另一方面,并行,则依赖于应用如何处理每个独立的任务。应用可以顺序的将任务从头至尾的执行完,也可以将任务分解成子任务,而子任务可以平行执行。
并发与顺序相对,而并行是并发的子集。
这里还有一个更形象的例子:
进程、线程和协程
进程(Process)
是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。
线程(Thread)
线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。
协程(Coroutine, Fiber)
协程,又称为微线程,在Lua、Python、Go中有所体现。这里参考廖雪峰的文章,举个例子:
如果有两个子程序A和B:def A():
print '1'
print '2'
print '3'
def B():
print 'x'
print 'y'
print 'z'
对于这两个子程序,一次调用,一次返回,返回结果很有可能是:1
2
3
x
y
z
而协程看上去虽然也是子程序,但是在执行过程中,在子程序内部可以中断,然后转而执行别的子程序,在适当的时候在返回来接着执行。比如上面的两个子程序假设由协程执行,那么再执行A的过程中,可以随时终端,去执行B,B也有可能在执行过程中中断再去执行A,结果有可能是:1
2
x
y
3
z
有些类似多线程,但是协程的特点实在一个线程中执行。其优势就是具有极高的执行效率,因为执行过程中不需要县城切换,减少了CPU切换线程的开销。另一方面,避免了多线程的锁机制,不会存在同时的写冲突。
Java与协程
Java语言本身不支持协程,通过第三方的库、协程框架可以实现,如注明的akka,kilim等。