专栏首页章鱼的慢慢技术路浅谈进程、线程和协程三者之间的区别和联系

浅谈进程、线程和协程三者之间的区别和联系

一、进程、线程、协程

1,进程

经典定义:一个执行中程序的实例。系统中的每个程序都运行在某个进程的上下文中。(-摘自 CSAPP)

进程是系统资源分配的最小单位

2,线程(thread)

线程就是运行在进程上下文中的逻辑流。

线程是操作系统能够进行运算调度的最小单位。

3,协程

相对子例程而言,协程更为一般和灵活,但在实践中使用没有子例程那样广泛。

根据维基百科对子例程的描述:是一个大型程序中的某部分代码,由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。我可以将子例程理解为一个函数。

4,区别和联系

首先,进程提供给应用程序的关键抽象为:

  • 一个独立的逻辑控制流:它提供一个假象,好像我们的程序独占地使用处理器。
  • 一个私有的地址空间,它提供一个假象,好像我们的程序独占地使用内存系统。

从以上描述我可以看出,一个进程是一个独立进行的任务,它占用的系统资源有:地址空间,全局变量,文件描述符,硬件资源等。

进程出现的目的,是为了更好的利用CPU资源。例如:

假设有两个任务A和B,当A遇到IO操作,CPU默默的等待任务A读取完操作再去执行任务B,这样无疑是对CPU资源的极大的浪费。若在任务A读取数据时,让任务B执行,当任务A读取完数据后,再切换到任务A执行,这样就可以更好地利用CPU资源。这里的切换涉及到状态的保存,状态的恢复,需要有一个东西去记录任务A和任务B分别需要什么资源,怎样去识别任务A和任务B,这时进程就出现了。

因此,通过进程来分配系统资源,标识任务。

如何分配CPU去执行进程称之为调度,进程状态的记录,恢复,上下文切换(简称切换)。

其次,若上面提及的任务A是一个文本程序,需要接受键盘输入,将内容显示在屏幕上,还需要保存信息到硬盘中。

若只有一个进程,会造成同一时间只能干一样事的尴尬(当保存时,就不能通过键盘输入内容)。若有多个进程,每个进程负责一个任务,进程A负责接收键盘输入的任务,进程B负责将内容显示在屏幕上的任务,进程C负责保存内容到硬盘中的任务。这里进程A,B,C间的协作涉及到了进程通信问题,而且有共同都需要拥有的东西-------文本内容,不停的切换造成性能上的损失。若有一种机制,可以使任务A,B,C共享资源,这样上下文切换所需要保存和恢复的内容就少了,同时又可以减少通信所带来的性能损耗,那就好了。这时线程出现了。

因此,线程共享进程的大部分资源,并参与CPU的调度。

假设当涉及到大规模的并发请求连接时,例如有一万个人同时连接我的服务器,但系统资源有限,如果以线程作为处理单元,调内部系统资源的话大部分线程都处于等待状态,但用了协程就可以实现线程自己调度,不陷入内核级别的上下文切换。这时协程出现了。

因此,协程通过在线程中实现调度,避免了陷入内核级别的上下文切换造成的性能损失,进而突破了线程在IO上的性能瓶颈。

为什么协程不需要经过内核级别的上下文切换,我是这样认为的:

进程和线程都是操作系统自带的,协程是有些程序原生支持的,例如go,lua, 有些是后期版本才有的,比如python2.5 C#等。

二、小结

之前做游戏服务器时就对这块概念不是很清晰,现在做流媒体服务时又碰到了这样的困惑,因此专门看书思考整理了相关的知识点,网上也参考了许多例子。如果有错误还望及时指正。

在此引用一位从事服务器开发的前辈说的话:

核心只有一个,线程是操作系统调度,协程是用户态调度。 协程不必须是语言集成,例如C语言可以用setjmp/longjmp实现,也可以自己通过改变esp指针换栈实现协程。 协程本身跟高吞吐没任何关系,基于io多路复用+回调就可以实现高并发和高吞吐。引入协程是为了将回调逻辑变成线性同步逻辑。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Go语言相关练习_选择题(2)

    go语言中字符串是UTF-8编码并存储的,它语言不定长的字节,所以它不支持下标操作,因为没一个下标操作代表的是固定长度的字节,所以不能对字符串中某个字符单独赋值...

    Zoctopus
  • 用Python中的tkinter模块作图

    Zoctopus
  • 飞鱼科技游戏开发岗面试经验

    Zoctopus
  • 分布式和单机版定时任务,总结的太全了呀!

    节前有更新一篇定时任务的相关文章《延时消息之时间轮》,有朋友提出希望可以完整的介绍下常见的定时任务方案,于是便有了这篇文章。

    JAVA葵花宝典
  • 盘点实现定时任务的那些方案

    节前有更新一篇定时任务的相关文章《延时消息之时间轮》,有朋友提出希望可以完整的介绍下常见的定时任务方案,于是便有了这篇文章。

    用户1516716
  • Python篇-多进程与协程的理解与使用

    一 : 科普一分钟 尽管进程间是独立存在的,不能相互访问彼此的数据,但是在python中却存在进程间的通信方法,来帮助我们可以利用多核CPU也能共享数据....

    小小科
  • 源码分析Dubbo服务提供者、服务消费者并发度控制机制

    本文将详细分析<dubbo:service executes=""/>与<dubbo:reference actives = ""/>的实现机制,深入探讨Dub...

    丁威
  • 【编程课堂】 windows计划任务

    在学习了一些爬虫或者 web 开发等知识之后,常常我们会有这样的需求: 写了个爬取豆瓣电影的脚本,需要每天定时自动运行; 使用 django 开发了一个小小的博...

    Crossin先生
  • RecyclerView 删除元素后,点击报 IndexOutOfBoundsException 解决方法

    今天使用 RecyclerView ,删除某个元素后,再点击后面的元素,会奔溃: ...

    张拭心 shixinzhang
  • Redis的单元测试 - Redis mock

    ps: 为了把文件写对地方,需要在建立test/resources/application.properties空文件

    十毛

扫码关注云+社区

领取腾讯云代金券