Thread(线程)、Fiber(纤程)、coroutine(协程) 、绿色线程(GreenThread)

计算机有进程,线程和协程。前两者大家都知道,很常见的玩意。而协程,则是基于线程之上的,自主开辟的异步任务,很多人更喜欢叫它们纤程(Fiber),或者绿色线程(GreenThread)。

  • 进程

为了使多个程序能够并发(同一时刻只有一个在运行,但感觉起来像多个同时运行;并行(同一时刻真的多个在运行,不是感觉像多个))的执行,操作系统需要一个结构来抽象和表示这个程序的运行。

进程是操作系统对一个正在运行的程序的一种抽象结构。
进程是指在操作系统中能独立运行并作为资源分配的基本单位,由一组机器指令、数据和堆栈等组成的能独立运行的活动实体。
操作系统可以同时运行多个进程,多个进程直接可以并发执行和交换信息。
进程在运行是需要一定的资源,如CPU、存储空间和I/O设备等。

  • 线程

自从摩尔定律被打破后,出现了多核CPU。为了更高效的进行调度,提出了比进程更轻量的独立运行和调度的基本单位:线程。

线程比进程更轻量
线程能独立运行,独立调度,拥有资源(一般是CPU资源,程序计数器等)
线程调度能大幅度减小调度的成本(相对于进程来说),线程的切换不会引起进程的切换
线程的引入进一步提高了操作系统的并发性,线程能并发执行
同一个进程的多个线程共享进程的资源(省去了资源调度现场保护的很多工作)

  • 协程、共行程序、Coroutine、纤程

协程是用户模式下的轻量级线程,协程的调度完全有应用程序来控制,操作系统不管这部分的调度线程和进程是由操作系统硬件控制的

它的出现我觉得是对线程的补充,每创建一个线程包含了实例化->分配资源->使用->gc销毁(中间还有可能很多上下文的切换)。协程就是想不用创建线程,就在当前线程中通过代码层面实现任务的切换功能。

一个线程可以包含一个或多个协程
协程拥有自己的寄存器上下文和栈,协程调度切换时,将寄存器上下纹和栈保存起来,在切换回来时恢复先前保运的寄存上下文和栈
协程能保留上一次调用时的状态,看到这里各种生成器(生成器是被阉割的协程)的概念浮现出来了。。
Windows下的实现叫纤程

 

协程的特点:

  1. 线程的切换由操作系统负责调度,协程由用户自己进行调度,因此减少了上下文切换。
  2. 线程的默认Stack大小是1M,而协程更轻量,接近1K。因此可以在相同的内存中开启更多的协程。
  3. 由于在同一个线程上,因此可以避免竞争关系而使用锁。

为什么我会说到协程,这个很多java程序员都没用过的东西。第一、吸引眼球!

好了,言归正传。

是springboot2.0 webflux发布之后,很多人大呼精彩,开始各种比较他与传统selvet性能高低。其实不然,webflux的模式其实和servlet3的模式殊途荣归,都是属于线程委派模式,将业务线程丢给另外的线程池处理来达到业务异步的效果。这样的确能提高某些情况下的吞吐量,但是却不是能达到的理想状态。

为什么这么说,因为我们假如业务线程池设置的最大线程数是1000,那么在核心线程数处理不过来的时候,就会不断的新增线程数直到1000,这样系统中就会出现大量的上下文切换而导致性能损耗。

这里补充一下:CPU线程数代表能同时处理多少线程任务,至于多出来的线程任务,则是CPU根据时间片或阻塞状态不断切换线程来执行,而切换线程的时候,则需要保存当前线程的状态,和恢复要切换的线程状态,这种对性能损耗很大的。

上下文切换的规则是一个线程运行超过5ms,或者出现阻塞,比如IO操作。

而一般像我们CURD程序员的业务操作离不开大量的IO操作(数据库读写),因此,将业务丢在一个线程池中,轮到CPU给你时间片的时候,你立马就告诉CPU:走吧走吧,我还在阻塞呢。 然后让线程立马就切换,可想而知这不是一个理想的操作。同时随着线程的增大,你的内存也不断在增大。

那么这个时候我们该如何处理呢?协程,对了~

协程是怎么来处理的呢,就是对于一个阻塞的业务操作,我们不是用线程来处理,而是用用协程,这样当出现IO阻塞的时候,并且你还没运行完时间片,你不会让CPU跑掉,而是调起你的另一个协程任务,让他继续进行计算。而通常我们知道,代码纯计算执行是非常快的,5ms可能跑了N个方法了,因此这样充分的利用时间片,并且减少CPU切换的时间。

其实在go,以及kotlin中,早已原生支持了协程的概念,所以go以及kotlin的ITer会相对javaer更多的了解协程。

此时javaer欲哭无泪啊。

但是我们真的就不能用协程了吗?虽然java官方还未支持,但是确有第三方支持的,下面给大家介绍下。

 

Quasar

一个比较成熟的java三方协程库,熟悉之后可用于生产环境。

 

Alibaba Dragonwell

阿里巴巴开源的发行版jdk,老爸是阿里内部的ajdk,但是目前ajdk的协程还没继承过来,说法是在慢慢继承。

 

Project Loom

oracle的jvm级项目,重新实现线程模型,里面包含协程方案,目前Quasar作者已经加入。(oracle忙着发JDK呢,这个还在无限延期)

kotlin

kotlin原生支持携程,且也是基于jvm运行的语言并且可以相互调用,可以考虑相互协作。

好了,说了这么多,其实就是一句话,目前现成的像样点的纯种协程框架就只有quasar,混种的就用kotlin吧。至于quasar,会在后续文章中继续介绍。

你可能感兴趣的:(#,并发编程)