美文网首页
线程、进程、协程那些事

线程、进程、协程那些事

作者: fanlv | 来源:发表于2018-07-11 17:11 被阅读75次

    基础概念

    一、什么是进程

    进程 是系统进行资源分配和调度的基本单位,是操作系统结构的基础。进程是程序基本执行的实体。进程与进程直接是完全独立的,拥有完全独立的地址空间。进程的切换只发生在内核态,由操作系统调度。

    二、什么是线程

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

    默认情况下,线程栈的大小为1MB。在VS2010的默认情况下,32位程序可以申请的堆大小最大是2G。实际上只能小于2G,所以在线程开到2000多个以上,会报Stack Overflow的错误。而64位程序,如果没有虚拟内存(硬盘)的支持,则可以使用128G的内存(比如说,你有8G内存,就可以使用8G内存)。而如果你把虚拟内存开启,则可以理论上得到16TB的内存使用大小[2].

    内核级线程

    1. 线程的创建、撤销和切换等,都需要内核直接实现,即内核了解每一个作为可调度实体的线程。
    2. 这些线程可以在全系统内进行资源的竞争。
    3. 内核空间内为每一个内核支持线程设置了一个线程控制块(TCB),内核根据该控制块,感知线程的存在,并进行控制。
      在一定程度上类似于进程,只是创建、调度的开销要比进程小。有的统计是1:10

    用户级线程

    1. 用户级线程仅存在于用户空间。——>对比内核(3)
    2. 内核并不能看到用户线程。——>重要的区别
    3. 内核资源的分配仍然是按照进程进行分配的;各个用户线程只能在进程内进行资源竞争。

    Linux历史上线程的3种实现模型

    1. 多对一用户线级程模型,多对一线程模型中,线程的创建、调度、同步的所有细节全部由进程的用户空间线程库来处理。用户态线程的很多操作对内核来说都是透明的,因为不需要内核来接管,这意味不需要内核态和用户态频繁切换。线程的创建、调度、同步处理速度非常快。当然线程的一些其他操作还是要经过内核,如IO读写。这样导致了一个问题:当多线程并发执行时,如果其中一个线程执行IO操作时,内核接管这个操作,如果IO阻塞,用户态的其他线程都会被阻塞,因为这些线程都对应同一个内核调度实体。在多处理器机器上,内核不知道用户态有这些线程,无法把它们调度到其他处理器,也无法通过优先级来调度。这对线程的使用是没有意义的!
    2. 一对一内核极线程模型 ,一对一模型中,每个用户线程都对应各自的内核调度实体。内核会对每个线程进行调度,可以调度到其他处理器上面。当然由内核来调度的结果就是:线程的每次操作会在用户态和内核态切换。另外,内核为每个线程都映射调度实体,如果系统出现大量线程,会对系统性能有影响。但该模型的实用性还是高于多对一的线程模型。
    3. 多对多两极线程模型,多对多模型中,结合了1:1和M:1的优点,避免了它们的缺点。每个线程可以拥有多个调度实体,也可以多个线程对应一个调度实体。听起来好像非常完美,但线程的调度需要由内核态和用户态一起来实现。可想而知,多个对象操作一个东西时,肯定要一些其他的同步机制。用户态和内核态的分工合作导致实现该模型非常复杂。NPTL曾经也想使用该模型,但它太复杂,要对内核进行大范围改动,所以还是采用了一对一的模型!!!

    三、什么是协程

    • 协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。执行协程只需要极少的栈内存(大概是4~5KB)

    协程的优点

    1. 跨平台
    2. 跨体系架构
    3. 无需线程上下文切换的开销
    4. 无需原子操作锁定及同步的开销
    5. 方便切换控制流,简化编程模型
    6. 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

    协程的使用场景

    一个线程内的多个协程是串行执行的,不能利用多核,所以,显然,协程不适合计算密集型的场景。协程适合I/O 阻塞型。
    I/O本身就是阻塞型的(相较于CPU的时间世界而言)。就目前而言,无论I/O的速度多快,也比不上CPU的速度,所以一个I/O相关的程序,当其在进行I/O操作时候,CPU实际上是空闲的。

    四、进程、线程、协程区别:

    • 进程:独立的栈空间,独立的堆空间,进程之间调度由os完成。

    • 线程:独立的栈空间,共享堆空间,内核线程之间调度由os完成。

    • 协程:独立的栈空间,共享堆空间,调度由用户自己控制,本质上有点类似于用户级线程,这些用户级线程的调度也是自己实现的。

    参考文章

    Linux用户级线程和内核级线程区别

    关于栈、堆、静态存储区最大可分配大小的探讨 转

    协程的使用场景

    协程的好处有哪些?

    相关文章

      网友评论

          本文标题:线程、进程、协程那些事

          本文链接:https://www.haomeiwen.com/subject/pqzhpftx.html