大家好,我是煎鱼。

最近金三银四,是面试的季节。在我的 Go 读者交流群里出现了许多小伙伴在讨论自己面试过程中所遇到的一些 Go 面试题。

今天的男主角,是工程师的必修技能,那就是 “什么是协程,协程和线程的区别和联系?

既要理解线程,还要讲解协程,并且诠释两者间的区别,但是由于提到线程,就必然涉及进程,因此本文将会同时梳理介绍 “进程、协程、协程” 三者的随笔知识,希望能引发大家的一些思考。

吸鱼之路开始。

进程

进程是什么

进程是操作系统对一个正在运行的程序的一种抽象,进程是资源分配的最小单位。

进程在操作系统中的抽象表现

为什么有进程

为什么会有 ”进程“ 呢?说白了还是为了合理压榨 CPU 的性能和分配运行的时间片,不能 “闲着“。

在计算机中,其计算核心是 CPU,负责所有计算相关的工作和资源。单个 CPU 一次只能运行一个任务。如果一个进程跑着,就把唯一一个 CPU 给完全占住,那是非常不合理的。

那为什么要压榨 CPU 的性能?因为 CPU 实在是太快,太快,太快了,寄存器仅仅能够追的上他的脚步,RAM 和别的挂在各总线上的设备则更是望尘莫及。

多进程的缘由

如果总是在运行一个进程上的任务,就会出现一个现象。就是任务不一定总是在执行 ”计算型“ 的任务,会有很大可能是在执行网络调用,阻塞了,CPU 岂不就浪费了?

进程的上下文切换

这又出现了多进程,多个 CPU,多个进程。多进程就是指计算机系统可以同时执行多个进程,从一个进程到另外一个进程的转换是由操作系统内核管理的,一般是同时运行多个软件。

线程

有了多进程,想必在操作系统上可以同时运行多个进程。那么为什么有了进程,还要线程呢?

原因如下:

  • 进程间的信息难以共享数据,父子进程并未共享内存,需要通过进程间通信(IPC),在进程间进行信息交换,性能开销较大。

  • 创建进程(一般是调用 fork 方法)的性能开销较大。

大家又把目光转向了进程内,能不能在进程里做点什么呢?

进程由多个线程组成

一个进程可以由多个称为线程的执行单元组成。每个线程都运行在进程的上下文中,共享着同样的代码和全局数据。

多个进程,就可以有更多的线程。多线程比多进程之间更容易共享数据,在上下文切换中线程一般比进程更高效

原因如下:

  • 线程之间能够非常方便、快速地共享数据。

    • 只需将数据复制到进程中的共享区域就可以了,但需要注意避免多个线程修改同一份内存。

  • 创建线程比创建进程要快 10 倍甚至更多。

    • 线程都是同一个进程下自家的孩子,像是内存页、页表等就不需要了。

协程是怎么回事

协程是什么

协程(Coroutine)是用户态的线程。通常创建协程时,会从进程的堆中分配一段内存作为协程的栈。

线程的栈有 8 MB,而协程栈的大小通常只有 KB,而 Go 语言的协程更夸张,只有 2-4KB,非常的轻巧。

协程的诞生

根据维基百科的说法,马尔文·康威于 1958 年发明了术语 “coroutine” 并用于构建汇编程序,关于协程最初的出版解说在 1963 年发表。

也就是历史上是先有的 “协程”,再有的 “线程”,线程是在在协程的基础上添加了栈等功能后扩展出来的。

但为什么一开始协程没有火起来呢?这个比较难考证,大概率还是与 60 年前的计算机时代背景有关。

而如今人们把协程调度的逻辑更进一步抽象为 “等 IO,让出,IO 完毕”,在此基础上人们发现协程的方式能解决多线程环境下很多代码逻辑 “混乱”。

协程的优势

既然线程似乎已经很好地填补了进程的遗憾,那怎么又出来了一个 “协程”,难道是重复造轮子吗?

协程的优势(via InfoQ @八两)如下:

  • 节省 CPU:避免系统内核级的线程频繁切换,造成的 CPU 资源浪费。好钢用在刀刃上。而协程是用户态的线程,用户可以自行控制协程的创建于销毁,极大程度避免了系统级线程上下文切换造成的资源浪费。

  • 节约内存:在 64 位的Linux中,一个线程需要分配 8MB 栈内存和 64MB 堆内存,系统内存的制约导致我们无法开启更多线程实现高并发。而在协程编程模式下,可以轻松有十几万协程,这是线程无法比拟的。

  • 稳定性:前面提到线程之间通过内存来共享数据,这也导致了一个问题,任何一个线程出错时,进程中的所有线程都会跟着一起崩溃。

  • 开发效率:使用协程在开发程序之中,可以很方便的将一些耗时的IO操作异步化,例如写文件、耗时 IO 请求等。

协程本质上就是用户态下的线程,所以也有人说协程是 “轻线程”,但我们一定要区分用户态和内核态的区别,很关键。

总结

归归根到底,在日常或面试中遇到 “什么是协程,协程和线程的区别和联系?” 这类问题时,面试者常规会把进程、线程、协程都介绍一遍。

为了方便记忆和诠释,推荐大家结合故事来讲会比较好,这一块可以参考阮一峰大神翻译的《进程与线程的一个简单解释》,会带来不少好感。

而最关键的部分,在于协程和线程的区别和联系是什么

我们可以通过文章中的介绍,从协程 -> 线程的历史进程来说明。接着进一步对比协程和线程两者的优势和缺点,就能比较好的诠释区别和联系了。

更优秀的部分,可以诠释完基本概念和区别后,进一步延伸都你所面试的岗位,例如是 Go 语言,就可以介绍 Go 语言的协程的具体应用和实现。

毕竟,Go 语言可以轻轻松松开数十万个协程,毫无波澜。这样能够更好的体现你对协程、线程的知识深度和广度应用,而不是单纯的背概念。

参考

  • 线程和进程的区别是什么?

  • 有了多线程,为什么还要有协程?

  • 进程与线程的一个简单解释


关注煎鱼公众号,吸取精华:

???? 点击关注煎鱼,在知识的海洋里遨游

学习资料分享,关注公众号回复指令:

  • 回复【000】,下载 LeetCode 题解大全。

  • 回复【001】,下载 Go 进阶图书 Mastering Go。

  • 回复【002】,加 Go 读者交流群。

Go 面试官:什么是协程,协程和线程的区别和联系?相关推荐

  1. 面试官:你说你懂i++跟++i的区别,那你会做下面这道题吗?

    面试官:你说你懂i++跟++i的区别,那你知道下面这段代码的运行结果吗? 面试官:"说一说i++跟++i的区别" 我:"i++是先把i的值拿出来使用,然后再对i+1,++ ...

  2. CSDN日报190929:面试官:兄弟,说说基本类型和包装类型的区别吧

    CSDN日报来啦!给大家奉上当日最新鲜的技术干货! 深度学习|[深度学习] 自然语言处理-Attention 作者:小墨鱼~~ 要了解深度学习中的注意力模型,就不得不先谈Encoder-Decoder ...

  3. 面试官:如何停止一个正在运行的线程?我一脸蒙蔽...

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:cnblogs.com/greta/p/5624839.ht ...

  4. 面试官:兄弟,说说 ArrayList 和 LinkedList 有什么区别

    作者 | 沉默王二 来源 | 沉默王二(ID:cmower) ArrayList 和 LinkedList 有什么区别,是面试官非常喜欢问的一个问题.可能大部分小伙伴和我一样,能回答出"Ar ...

  5. .实现 linkedlist 类java_面试官:兄弟,说说 ArrayList 和 LinkedList 有什么区别

    来自公众号:沉默王二 ArrayList 和 LinkedList 有什么区别,是面试官非常喜欢问的一个问题.可能大部分小伙伴和我一样,能回答出"ArrayList 是基于数组实现的,Lin ...

  6. 面试官 | count(1)、count(*) 、count(列名) 有什么区别?

    作者 | BigoSprite 来源 | 39sd.cn/0926A 先看执行效果: 1.  count(1) and count(*) 当表的数据量大些时,对表作分析之后,使用count(1)还要比 ...

  7. 面试官问:你做过什么Java线程池实践,我写了一篇博客给他看~

    线程池大家都## 标题很熟悉,无论是平时的业务开发还是框架中间件都会用到,大部分都是基于JDK线程池ThreadPoolExecutor做的封装, 都会牵涉到这几个核心参数的设置:核心线程数,等待(任 ...

  8. 1.Unity协程、进程、线程的区别

    1.进程拥有自己独立的堆和栈,堆和栈都不共享,进程由操作系统调度. 2.线程有自己独立的栈和共享的堆,栈不共享,堆共享,标准的线程也是由系统调度. 3.协程有自己独立的栈和共享的堆,栈不共享,堆共享, ...

  9. 腾讯面试官:如何停止一个正在运行的线程?我蒙了。。。

    以下文章来源方志朋的博客,回复"666"获面试宝典 停止一个线程意味着在任务处理完任务之前停掉正在做的操作,也就是放弃当前的操作.停止一个线程可以用Thread.stop()方法, ...

  10. 面试官问我:spring、springboot、springcloud的区别,我笑了

    好吧,可能某些项目还在使用dubbo,但是你也一定听过Spring Cloud.至于Spring和Spring Boot,对于现在的Java开发,它们的地位简直可以说是不可或缺了.如果你的新项目在使用 ...

最新文章

  1. Swift: 可变参数
  2. Py之GUI:Python下各种GUI(图形用户界面)简介、使用优缺点对比
  3. 共识协议(8)NPOS提名权益证明
  4. boost::container模块实现范围分配器用法
  5. python 电脑文件变动提醒_Python整理文件方法,效率提升100倍-docx是什么文件
  6. Eclipse无法设置NDK路径的解决方法
  7. 全国省市区数据SQL - 2017年数据(三级联动)
  8. c语言仿宋gb2312字体,【仿宋gb2312字体下载】仿宋gb2312字体官方下载 免费版-七喜软件园...
  9. 论坛mysql表设计_网站论坛如何制作—简单论坛数据库的设计与操作
  10. 5款考试学习的高效率APP,让你轻松学习一整天!
  11. splunk篇5-导出csv文件中文乱码
  12. 奖励补贴有点多!武汉市大健康和生物技术产业发展奖励措施解读
  13. YCbCr(YUV)与RGB转换公式以及常用颜色的yuv值
  14. linux extended格式,Linux 下文件Non-ISO extended-ASCII编码问题
  15. Bmob关联Android,bmob-android-im-sdk
  16. linux使用gcc实现扫雷,基于linux环境下扫雷应用程序
  17. getBytes()方法详解
  18. MySQL 数据库 varchar 到底可以存多少个汉字,多少个英文呢?我们来搞搞清楚
  19. 读锁应该插队吗?什么是读写锁的升降级?
  20. C#调用斑马打印机打印条码标签(含源码)(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)

热门文章

  1. 线束测试仪,贯穿航空线束线缆组件减重安全性检验
  2. tensorflow cudart64_101.dll 版本问题
  3. qq令牌码怎么提取_和平精英王者荣耀微视集令牌活动玩法介绍 王者荣耀英雄令怎么刷...
  4. Map集合循环遍历的几种方式
  5. 对华为来说,Mate40 不只是产品,而是一种生命力的宣言
  6. 小程序ios时间格式 yyyy/MM/dd
  7. 做卫星的企业进军分布式存储领域 ?
  8. 传统的计算机软件以产品形式,A04 基本知识-软件初探.pdf
  9. 如何使用 JavaScript 过滤 HTML 表格(在 HTML 表格上搜索)
  10. python for if