kotlinKotlinKotlin

kotlin之协程(一),线程,进程,协程,协程可以替换线程吗?

2020-10-29  本文已影响0人  不思进取的码农

目录

kotlin之协程(一),线程,进程,协程,协程可以替换线程吗?
kotlin之协程(二),Kotlin协程是什么、挂起是什么、挂起的非阻塞式
kotlin之协程(三),开始创建协程,launch,withContext
kotlin之协程(四),协程的核心关键字suspend
kotlin之协程(五),launch 函数以及协程的取消与超时
kotlin之协程(六),协程中的 async和launch的区别以及runBlocking
kotlin之协程(七),协程中relay、yield 区别

前言

在DataStore里面有提到 DataStore是基于协程Flow实现的,那么什么是协程呢?

先来回顾一下线程和进程

在了解协程之前,我们先回归一下进程和线程的概念

线程进程.jpeg

总结起来就是:对操作系统来说,线程是最小的执行单元,进程是最小的资源管理单元

无论进程还是线程都是有操作系统统一管理的
而线程具有五种状态,我们看一下状态的转化关系


线程转化关系.png

接下来我们了解一下并发和并行

即使其中只有一个线程在运行,也可以有一个并发应用程序

并行.png

为了实现真正的并行性,您的应用程序必须运行多个线程,或者至少能够调度要在其他线程,进程,CPU,图形卡等中执行的任务。

不得不说的进程和线程的痛点

(1)线程的调度与缺点

在同一个进程中并行运行多个线程,是对在同一台计算机上并行运行多个进程的模拟。因此,线程也被称为轻量级进程。与进程调度类似,CPU在线程之间快速切换,制造了线程并行运行的假象。

由于各个线程都可以访问进程地址空间的每一个内存地址,所以一个线程可以读、写,甚至清除另一个线程的堆栈。也就是说,线程之间是没有保护的。但要注意的是,每个线程都有自己的堆栈、程序计数器、寄存器等信息,这些不是共享的。

共享地址空间虽然可以方便地共享对象,但这也导致一个问题,那就是任何一个线程出错时,进程中的所有线程会跟着一起崩溃。这也是如Nginx等强调稳定性的服务坚持使用多进程模式的原因。事实上,无论基于多进程还是多线程,都难以实现高并发,这由三个原因所致

(2)线程内存占用

一是单个线程消耗的内存过多,比如64位的Linux为每个线程的栈分配了8MB的内存,通过ulimit -s可以查看线程的默认分配的内存。单位kb

(3)线程竞争

为了解决线程申请堆内存时,互相竞争的问题。每个线程预先在这个空间内申请堆空间还预分配了64MB的内存作为堆内存池。所以,我们没有足够的内存去开启几万个线程实现并发。

(4)线程切换耗时

线程的切换是由内核控制的,什么时候会切换线程呢?不只时间片用尽,当调用阻塞方法时,内核为了CPU 充分工作,也会切换到其他线程执行。一次上下文切换的成本在几十纳秒到几微秒间,当线程繁忙且数量众多时,这些切换会消耗绝大部分的CPU运算能力。

下图以磁盘IO为例,描述了多线程中使用阻塞方法读磁盘,2个线程间的切换方式。

线程切换耗时.png

那么,怎么才能实现高并发呢?把上图中本来由内核实现的请求切换工作,交由用户态的代码来完成就可以了。

协程

什么是协程

协程 - 也叫微线程,是一种新的多任务并发的操作手段

这中说话不够详细,我们换种说话

协程就是用户态的线程。通常创建协程时,会从进程的堆中分配一段内存作为协程的栈。线程的栈有8MB,而协程栈的大小通常只有几十 KB,更低的内存占用空间为高并发提供了保证

协程的开发人员 Roman Elizarov 是这样描述协程的:协程就像非常轻量级的线程。线程是由系统调度> 的,线程切换或线程阻塞的开销都比较大。而协程依赖于线程,但是协程挂起时不需要阻塞线程,几乎>是无代价的,协程是由开发者控制的。所以协程也像用户态的线程,非常轻量级,一个线程中可以创建>任意个协程。

对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序。协程能保留上一次调用时的状态,不需要像线程一样用回调函数,所以性能上会有提升。缺点是本质是个单线程,不能利用到单个CPU的多个核

协程的调度

语言的运行时系统会帮助我们自动地创建和销毁系统级的线程。这里的系统级线程指的就是我们刚刚说过的操作系统提供的线程。

PHP协程的问题

为了保证所有切换都在用户态进行,协程必须重新封装所有的阻塞系统调用,否则,一旦协程触发了线程切换,会导致这个线程进入休眠状态,进而其上的所有协程都得不到执行。所以,协程的高性能,建立在切换必须由用户态代码完成之上,这要求协程生态是完整的,要尽量覆盖常见的组件

为什么要搞出和用协程呢

对于协程的一个总结

写到最后

协程本身不是替换线程的,因为协程是建立在线程之上的,但是协程能够更好的为我们提供执行高并发任务
但是kotlin的协程的概念是否真的是这样的呢?

(每天学习一点点.每天进步一点点,分享不宜路过点个赞呀,喜欢的点个关注后续更新不断).

上一篇下一篇

猜你喜欢

热点阅读