

















进程,线程和协程
Process, Thread and Coroutine
理论篇
分类: 编程 / 字数: 3358 / 标签: 进程, Process, 线程, Thread, 协程, Coroutine, 进程间通讯, inter-process communicate, IPC, 生成器, Generator, 迭代器, Iterator, 并发性, 并行性, 临界区段, Critical Section, 同步原语, 锁, 互斥锁, Mutual Exclusion, Mutex, 信号量, Semaphore, 进程间通信, 管道, Pipe, Pipeline, 命名管道, Named Pipe, 信号, Signal, 消息队列, Message Queue, 信号量, Semphore, 共享内存, Shared Memory, 伯克利套接字, Internet Berkeley Sockets, BSD 套接字, BSD Sockets, 网络套接字, Network Socket, 线程间通信, 读写锁, 条件变量, 自旋锁
Python 实现篇请参见:进程,线程和协程 (Process, Thread and Coroutine) - 实现篇
进程(Process)是计算机中已运行的程序 1。线程(Thread)是操作系统能够进行运算调度的最小单位。大部分情况下,线程被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 2。
进程和线程之间的主要区别在于:
单线程进程和多线程进程之间的对比如下图所示:
一个关于进程和线程的形象类比如下 3:
$n$ 个人,比如厨房。也就是说,如果人数大于 $n$,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。$n$ 把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种做法叫做“信号量”(Semaphore),用来保证多个线程不会互相冲突。不难看出,Mutex 是 Semaphore 的一种特殊情况($n = 1$ 时)。也就是说,完全可以用后者替代前者。但是,因为 Mutex 较为简单,且效率高,所以在必须保证资源独占的情况下,还是采用这种设计。协程(Coroutine)是计算机程序的一类组件,推广了协作式多任务的子例程,允许执行被挂起与被恢复。相对子例程而言,协程更为一般和灵活,但在实践中使用没有子例程那样广泛。协程更适合于用来实现彼此熟悉的程序组件,如协作式多任务、异常处理、事件循环、迭代器、无限列表和管道。
子例程(Subroutine),是一个大型程序中的某部分代码,由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。
协程和子例程的执行过程对比如下:
yield 返回出口点都是再次被调用执行时的入口点。yield 时不调用其他协程,而是每次返回一部分的结果值,这种协程常称为生成器或迭代器。协程类似于线程,但是协程是协作式多任务的,而线程是抢占式多任务的。这意味着协程提供并发性而非并行性。协程超过线程的好处是它们可以用于硬性实时的语境(在协程之间的切换不需要涉及任何系统调用或任何阻塞调用),这里不需要用来守卫临界区段的同步原语比如互斥锁、信号量等,并且不需要来自操作系统的支持。
管道(Pipeline)是一系列将标准输入输出链接起来的进程,其中每一个进程的输出被直接作为下一个进程的输入。 例如:
ls 用于在 Unix 下列出目录内容,less 是一个有搜索功能的交互式的文本分页器。这个管道使得用户可以在列出的目录内容比屏幕长时目录上下翻页。
命名管道是计算机进程间的一种先进先出通信机制。是类 Unix 系统传统管道的扩展。传统管道属于匿名管道,其生存期不超过创建管道的进程的生存期。但命名管道的生存期可以与操作系统运行期一样长。
信号(Signals)是 Unix、类 Unix 以及其他 POSIX 兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,任何非原子操作都将被中断。如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数。
例如,在一个运行的程序的控制终端键入特定的组合键可以向它发送某些信号:Ctrl + C 发送 INT 信号(SIGINT),这会导致进程终止;Ctrl + Z 发送 TSTP 信号(SIGTSTP),这会导致进程挂起。
消息队列提供了异步的通信协议,每一个贮列中的纪录包含详细说明的资料,包含发生的时间,输入设备的种类,以及特定的输入参数,也就是说:消息的发送者和接收者不需要同时与消息队列交互。消息会保存在队列中,直到接收者取回它。
消息队列本身是异步的,它允许接收者在消息发送很长时间后再取回消息。和信号相比,消息队列能够传递更多的信息。与管道相比,消息队列提供了有格式的数据,这可以减少开发人员的工作量。
信号量(Semaphore)又称为信号标,是一个同步对象,用于保持在 0 至指定最大值之间的一个计数值。当线程完成一次对该 Semaphore 对象的等待(wait)时,该计数值减一;当线程完成一次对 Semaphore 对象的释放(release)时,计数值加一。当计数值为 0,则线程等待该 Semaphore 对象不再能成功直至该 Semaphore 对象变成 signaled 状态。Semaphore 对象的计数值大于 0,为 signaled 状态;计数值等于 0,为 nonsignaled 状态.
共享内存指可被多个进程存取的内存,一个进程是一段程序的单个运行实例。在这种情况下,共享内存被用作进程间的通讯。
伯克利套接字(Internet Berkeley Sockets),又称为 BSD 套接字是一种应用程序接口,主要用于实现进程间通讯,在计算机网络通讯方面被广泛使用。
同上文。
同上文。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。