进程 线程 协程 异步编程模型

线程

对于操作系统而言,线程是最小的执行单元,进程是最小的资源管理单元。无论是进程还是线程,都又操作系统管理

在I/O(DiskIO、网络IO等)操作中,分片执行效率更高
在文件读取过程中有一个很重要的东西,叫DMA(Direct Memory Aaccess)直接存储访问

DMA:
它允许不同速度的硬件装置来沟通,而不需要依赖于CPU的大量中断负载。否则,CPU需要冲来源把每一片段的资料复制到寄存器,然后把他们再次写回到新的地方。在这个时间中,CPU对于其他工作来说就无法使用。
DMA进行数据读取是可以复用的,CPU的总线具有多条线路,DMA就可以充分利用这些线路,最终实现并行的读取文件

硬盘I/O

在实际的操作中硬盘I/O的流程:

  1. CPU向DMA下达指令,指令包含磁盘设备信息和要读取的文件的位置,让DMA来完成文件的读取
  2. 将文件的内容加载内存中
  3. 读取完成后硬盘给DMA反馈读取完成,DMA给CPU一个中断,CPU再从硬盘中获得从硬盘中读取到的值

在CPU下达DMA指令后CPU就处于闲置状态,CPU就可以执行其他的线程,大大提高CPU的利用率

线程之间的协作

最经典的例子就是生产者/消费者模式,即若干个生产者线程向队列中存放数据,若干个消费者线程冲冲队列中消费数据

进程 线程 协程 异步编程模型_第1张图片

生产者和消费者模式的性能问题:

  • 涉及到同步锁
  • 涉及到线程阻塞状态和可运行状态的切换
  • 涉及到线程上下文的切换

协程

协程是一种比线程更加轻量级的存在,正如一个进程可以拥有多个线程一样,一个进程可以拥有多个协程

进程 线程 协程 异步编程模型_第2张图片

在进一步了解协程之前先了解两个概念

由于需要限制不同程序间的访问能力,防止他们获得别的程序的内存资源,或者获得外围的数据并发送到网络,CPU划分出的两个权限等级:用户态内核态
(1)内核态:CPU可以访问内存中所有的数据,包括外围设备,例如硬盘、网卡等,CPU也可以将自己从一个程序切换到另一个程序
(2)用户态:只能受限的访问内存,且不允许访问外围设备,占用CPU的能力内剥夺,CPU资源可以被其他程序获得

协程不是被操作系统内核管理的,而是完全由程序所控制,也就是在用户态执行的。这样带来的好处就是性能大幅度提升,因此不会像线程切换那样消耗资源

协程是一个特殊的函数,这个函数可以在某个地方挂起,并且可以重新在挂起处外继续运行。所以协程/进程/线程并不是一个维度的概念

一个线程可以包含多个协程,到那时必须明确一点,一个线程的多个协程是串行的。如果是多个CPU,多个进程或者说是一个进程中的多个线程是并行运行的,但是一个线程中的多个协程却是串行运行的。毕竟协程是一个特殊的函数,但毕竟是函数。当一个协程运行时,线程内的多个协程必须是挂起的

进程、线程、协程的对比

  • 协程既不是线程也不是进程,协程仅仅是一个特殊的函数,协程、线程和进程不是一个维度的
  • 一个进程可以包含多个线程,一个线程可以包含多个协程
  • 一个线程内的多个协程虽然可以切换,但是都是串行执行的,只能在一个线程内运行,没办法利用CPU的多核能力
  • 协程和进程一样,切换是存在上下文切换的问题

上下文切换

  • 进程的切换者是操作系统,切换实际是根据操作系统自己的切换策略,用户无感知。线程的切换内容包含全局目录、内核栈和硬件上下文,切换内容保存在内存中,进程切换是由“用户态到内核态到用户态”的切换方式,切换效率低

  • 线程的切换者是操作系统,切换实际是根据操作系统自己的切换策略,用户无感知。线程的切换包含内核栈和硬件上下文。线程切换内容保存在内核栈中。线程切换过程是由“用户态到内核态到用户态”,切换效率中等

  • 协程的切换者是用户(编程者或应用程序),切换时机是用户自己的程序所决定的。协程的切换内容是硬件上下文,切换内存保存在用户自己的变量(用户栈或堆)中。协程的切换只有用户态,没有陷入内核态,因此切换效率高。

异步

一开始提到的CPU调用DMA去读取硬盘,读取结束后在触发中断这个调用过程就是异步的
在Nodejs中默认就是异步编程,他单线程却能处理高并发得益于异步的操作方式
但是在Nodejs中有大量的异步就产生了大量的回调函数,后面陷入了回调地狱,对于效率没有太大的影响,但是对于程序员来说却是地狱,在他的发展过程中也提出了很多的解决方案

你可能感兴趣的:(Java学习笔记)