专栏首页会呼吸的Coder进程、线程、协程到底是个什么东西?

进程、线程、协程到底是个什么东西?

一、前言

不管是上大学课程《操作系统》,还是找工作面试,还是日常工作大家交流中,都离不开进程和线程,有些同学可能还会听说过协程。那他们到底是什么呢?他们之间有什么关系呢?跟着我一起往下看吧!

二、计算机组成及操作系统

在讲进程之前,我们先回顾一下计算机的组成。

  1. 中央处理器(CPU):是计算机的核心,负责一些运算和控制

CPU有两大核心部件,ALU(算数逻辑单元)和CU(逻辑控制单元),其中ALU负责一些运算,包括算数运算(加减乘除)、逻辑运算(与或非)及关系运算(大小等于);CU负责各个逻辑部件的协调工作,充当一个指挥官的角色。CPU中也有寄存器,只不过容量极小,负责缓存一些计算的中间结果。

  1. 主存储器:存储数据

分为RAM和ROM。RAM,随机存储器,掉电数据丢失,就是俗称的内存;ROM,只读存储器,掉电数据不丢失,就是俗称的磁盘。

  1. IO:各种输入输出设备(鼠标、键盘、显示器、网卡、声卡、显卡等)

有了这些计算机的硬件支持,我们就可以做各种各样的事情了。如果我们手动来控制CPU和内存,那我们可能要写各种底层指令,而且肯定会出现各种各样的bug。操作系统在计算机硬件的基础之上,封装了硬件的实现细节,对上层抽象了一层更方便的系统调用指令,这就是操作系统。

在多任务系统中,操作系统接管了所有硬件资源并持有对硬件控制的最高权限。在操作系统中执行的程序,都以进程的方式运行在更低的权限中。所有的硬件资源,由操作系统根据进程的优先级以及进程的运行状况进行统一的调配。

三、进程

有了操作系统,我们就能够在上面实现程序了。比如通过一个QQ来实现聊天功能。那QQ程序怎么启动起来呢,操作系统把QQ程序丢在一个容器里并把它执行起来,而这个容器就是进程。那进程跟程序之间又是什么关系呢?

  • 程序是死的(只是在磁盘中的一堆指令代码),进程是活的(会占用CPU、内存、文件资源、IO等)
  • 进程是程序的运行实例

四、线程

维基百科:线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

一个进程有多个线程,拿QQ为例子,需要有一个线程监听键盘的输入并转换为文字,需要有一个线程负责拉取对方发来的消息等。从操作系统的角度来看:

  • 进程是最小的资源管理分配单元
  • 线程是最小的执行单元

无论是进程还是线程都是需要操作系统来控制的。拿线程来举例,线程有多个执行状态:初始化、可运行、运行中、阻塞、销毁 五种状态。这五种状态的转化关系如下:

线程状态转化图.png

线程的状态转化是由操作系统内核中的TCB(thread control block)线程控制块来改变的,需要耗费一定的CPU资源。

总结一下,进程是一个程序的运行实例,它管理着各种资源;一个进程有多个线程,线程才是具体的执行单元,他们共享着进程中的部分资源,同样有着私有资源(PC程序计数器、执行栈等),线程间默认通过共享内存进行交互,线程间同步通过锁/信号量等进行互斥操作。由于线程切换需要在操作系统在内核/用户态间的切换才能改变状态,导致线程切换本身会非常耗费资源。

五、协程

协程,又称微线程,纤程。英文名Coroutine。比线程更加轻量级,就像一个进程有多个线程一样,一个线程可以有多个协程。

举一个廖雪峰老师给的例子:

def a(): print 1 print 2 def b(): print 'A' print 'B'

当我们调用a、b这两个函数时,肯定会先后打印1 2 A B,如果我想打印1 A B 2 或者 1 A 2 B呢?显然通过多线程时不能控制的。这样我们就可以通过协程来处理。通过程序自身的逻辑来实现流程跳转,相比于线程中断,有点像CPU中断,不需要通过操作系统的介入,效率极高。

python语言本身支持协程,通过yield关键字来实现。

def a():
    print 1
    yield
    print 2
    yield
def b():
    print 'A'
    print 'B'
generator=a()
next(generator)
b()
generator.send('')

该语句就会打印:

1
A
B
2
  1. 通过调用a()生成一个执行器
  2. 通过next触发执行器执行a并打印1
  3. 调用b打印A和B
  4. 通过send像执行器发送信号继续执行并打印2

整个流程是由一个线程执行,通过一些语法来控制执行流程,不涉及到锁,不涉及到线程切换,是通过关键字来辅助a和b协作工作,所以叫做协程。

ES6中引入了for..of..,它本身是一个语法糖,原理是通过引入迭代器(iterator)来实现,而迭代器就是通过协程来实现的。而在ES7中引入了更加直观的async/await`。

java本身不支持协程,但可以通过三方库来实现,例如Quasar和Akka等。

本文分享自微信公众号 - 会呼吸的Coder(BreathCoder),作者:是灰灰呀s

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-20

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Mysql锁总结

    数据库锁设计的初衷是处理并发问题。作为多用户共享的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则。而锁就是用来 实现这些访问规则的重要数据结构

    会呼吸的Coder
  • 一系列有用的Python技巧

    幸好,Python的标准库提供了collections模块,它为您提供了更多的数据类型

    会呼吸的Coder
  • Windows下安装Python3

    “ 为什么制作windows下的教程,是因为Ubuntu系Linux发行版和mac已经集成了python”

    会呼吸的Coder
  • 面试题-JAVA之重入锁ReentrantLock

    并发场景下如何保证线程安全,首先就会想到Synchronized,是的没错但是今天我们来看一下和syn锁具有相同作用而且扩展性更高的锁ReentrantLock...

    别明天就今天吧
  • 18 Python 基础: 重点知识点--进程和线程讲解

    本文首发于腾讯云+社区,也可关注微信公众号【离不开的网】支持一下,就差你的关注支持了。

    小Gy
  • java线程池(三):ThreadPoolExecutor源码分析

    在前面分析了Executors工厂方法类之后,我们来看看AbstractExecutorService的最主要的一种实现类,ThreadpoolExecutor...

    冬天里的懒猫
  • python线程、协程

    如果同一时间有多个线程操作同一数据可能会出现混乱现象,所以需要加线程锁保证同一时间只有一个线程操作这一数据,保证数据一致性

    py3study
  • Java并发编程--Lock

      Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。synchronized方法或代码块的使用提供了对与每个对象相关的...

    在周末
  • 让人头大的各种锁,从这里让你思绪清晰

    说到了锁我们经常会联想到生活中的锁,在我们日常中我们经常会接触到锁。比如我们的手机锁,电脑锁,再比如我们生活中的门锁,这些都是锁。

    程序员小明
  • 让人头大的各种锁,从这里让你思绪清晰

    说到了锁我们经常会联想到生活中的锁,在我们日常中我们经常会接触到锁。比如我们的手机锁,电脑锁,再比如我们生活中的门锁,这些都是锁。

    用户1516716

扫码关注云+社区

领取腾讯云代金券