11 | 多任务:进程、线程与协程-笔记

早期CPU都是单核的,同一时间只能处理单一的任务

摩尔定律只是模糊的经验理论 不能作为计算机发展的理论

如何处理?

横向多铺几个核心

物理多任务的方法:

1.多颗CPU

2. 一颗CPU 多核心


现在的计算机,大多数是后者,然而服务器大多数结合以上两点,用来提高算力


单核有办法实现多任务吗?

可以给CPU的时间进行切片处理,且片的范围很小, 每一运行不同的软件。从而给用户一种软件同时在运行的感觉

这种方式,我们称其为 “分时系统”

这种方式通常使用保存任务状态和状态恢复的方式来操作软件进程

问题:

什么是任务?如何抽象?

怎么恢复和保存?

什么时机可以切换?

任务的抽象不是唯一的

大部分操作系统 提供了 进程 线程

还有的操作系统提供了协程 (纤程)

许神 将上述概念统称为“执行体”:可以被CPU赋予执行权限的对象 他至少包含了下一个执行位置、执行状态

任务都有什么状态?

CPU依赖的是寄存器和RAM

寄存器

architect11-1

内存

architect11-2


进程与线程

看不同请见下表



不同进程遵守最低授权原则

创建进程

UNIX 是 fork 一个新的,各干各的

糟糕的设计同时也被LINUX继承了

进程是最基础的隔离单元 但是偏要藕断丝连

windows 是通过句柄的方式 需要什么拿什么

许神的经验是  除了接管子进程的标准 输入输出,我们几乎从来不会通过向子进程传递文件句柄来通讯。

因此 fork这种方式 是一种过度设计

线程这种方式的出现,是因为同一软件会有多任务的需求,且任务是存在于同一地址空间,且能够互相信任

从线程的角度去理解UNIX的fork,可能会理解当年的设计角度

早期的操作系统没有考虑到软件的这种需求,因此现在的进程仍然需要考虑到线程的需求,例如需要父进程的执行环境(上下文)

协程与 goroutine

用户态进程 不由系统提供

目的:

为了实现高性能的网络服务 常规的程序 例如桌面程序 进程而加上线程已经足够了

简单模型:


大量的 请求和响应 往往需要存储以及读取自身的状态 这个时候会存在大量的本地以及网络IO

系统提供的网络IO:

系统调用机制的开销

数据多次拷贝的开销

没有数据而阻塞 从新获得执行权而产生的时间成本

线程的空间和时间成本

系统调用的速度不慢

归根结底还是一次函数调用的成本

例如:


内核主线程:是独立线程

系统调用角度来说,内核是多线程程序 每个系统调用来源都是某线程的函数调用

epoll(Linux)或 IOCP(Windows 是现在主流的改善吞吐效率的方式

在线程中查询谁先完成就让谁执行

产生了多次系统调用 但是减少了线程的数量

可以了解 libevent 

Node.js 一炮而红 ,注释: 结合了JavaScript 的低门槛和 libevent 的高性能...

缺点: 容易让逻辑代码碎片化

线程的成本高吗?

时间成本:

执行体切换本身的开销

执行体的调度开销

执行体之间的同步与互斥成本。

空间成本:

执行体的状态

TLS (线程局部存储)

执行体堆栈

线程占据应该是MB单位 但是堆栈的成本比较高

协程的目的:

回归同步编程

降低执行体的空间、时间成本

大多数库只是实现了其中的创建和执行,缺乏调度、同步、互斥通讯、网络IO的请求包装

一个完备的协程库你可以把它理解为用户态的操作系统,而协程就是用户态操作系统里面的 “进程”。

Erlang 和 Go 语言干了这件事,具备完成的代码库

Erlang基于虚拟机, go 基于 goroutine

go:

堆栈开始很小 4k ,可无限拓展

干掉线程局部存储

同步 互斥 的特性  channel

提供了重要的系统调用 例如  IO 请求


操作系统内核是非常庞大而复杂的基础软件。它并不像计算机基础体...


极客时间版权所有: https://time.geekbang.org/column/article/96324


有疑问、勘误、请您在下方留言,感谢您的支持 ღ( ´・ᴗ・` )!

感谢您阅读,这篇文章归 极客点子版权所有.
如果转载,请注明出处: 极客点子版权所有(/page/946.html) 知识共享许可协议
本网站使用 创作共用 归属 - 非商业用途 - 共享4.0国际许可协议的相同方式 许可.

关于作者:

    作者:

    reverse()

    简介:

    nodejs 全栈工程师 、作家、github 开源爱好者
    研究方向:数据分析、 深度学习、 服务器架构、 系统原理

    著作:

    最爱的编程语言:

    Javascript
    Python