美文网首页Kotlin-Coroutines
协程(2)-到底什么是「非阻塞式」挂起?协程真的更轻量级吗?

协程(2)-到底什么是「非阻塞式」挂起?协程真的更轻量级吗?

作者: 沐风雨木 | 来源:发表于2020-06-21 16:16 被阅读0次

什么是「非阻塞式挂起」

非阻塞式是相对阻塞式而言的。

编程语言中的很多概念其实都来源于生活,就像脱口秀的段子一样。

线程阻塞很好理解,现实中的例子就是交通堵塞,它的核心有 3 点:

  • 前面有障碍物,你过不去(线程卡了)
  • 需要等障碍物清除后才能过去(耗时任务结束)
  • 除非你绕道而行(切到别的线程)

从语义上理解「非阻塞式挂起」,讲的是「非阻塞式」这个是挂起的一个特点,也就是说,协程的挂起,就是非阻塞式的,协程是不讲「阻塞式的挂起」的概念的。

我们讲「非阻塞式挂起」,其实它有几个前提:并没有限定在一个线程里说这件事,因为挂起这件事,本来就是涉及到多线程。

就像视频里讲的,阻塞不阻塞,都是针对单线程讲的,一旦切了线程,肯定是非阻塞的,你都跑到别的线程了,之前的线程就自由了,可以继续做别的事情了。

所以「非阻塞式挂起」,其实就是在讲协程在挂起的同时切线程这件事情。

为什么要讲非阻塞式挂起

既然第三篇说的「非阻塞式挂起」和第二篇的「挂起要切线程」是同一件事情,那还有讲的必要吗?

是有的。因为它在写法上和单线程的阻塞式是一样的。

协程只是在写法上「看起来阻塞」,其实是「非阻塞」的,因为在协程里面它做了很多工作,其中有一个就是帮我们切线程。

第二篇讲挂起,重点是说切线程先切过去,然后再切回来。

第三篇讲非阻塞式,重点是说线程虽然会切,但写法上和普通的单线程差不多。

让我们来看看下面的例子:

🏝️
main {
    GlobalScope.launch(Dispatchers.Main) {
        // 👇 耗时操作
        val user = suspendingRequestUser()
        updateView(user)
    }
    
    private suspend fun suspendingRequestUser() : User = withContext(Dispatchers.IO) {
        api.requestUser()
    }
}

从上面的例子可以看到,耗时操作和更新 UI 的逻辑像写单线程一样放在了一起,只是在外面包了一层协程。

而正是这个协程解决了原来我们单线程写法会卡线程这件事。

阻塞的本质

首先,所有的代码本质上都是阻塞式的,而只有比较耗时的代码才会导致人类可感知的等待,比如在主线程上做一个耗时 50 ms 的操作会导致界面卡掉几帧,这种是我们人眼能观察出来的,而这就是我们通常意义所说的「阻塞」。

举个例子,当你开发的 app 在性能好的手机上很流畅,在性能差的老手机上会卡顿,就是在说同一行代码执行的时间不一样。

视频中讲了一个网络 IO 的例子,IO 阻塞更多是反映在「等」这件事情上,它的性能瓶颈是和网络的数据交换,你切多少个线程都没用,该花的时间一点都少不了。

而这跟协程半毛钱关系没有,切线程解决不了的事情,协程也解决不了。

协程与线程

协程我们讲了 3 期,Kotlin 协程和线程是无法脱离开讲的。

别的语言我不说,在 Kotlin 里,协程就是基于线程来实现的一种更上层的工具 API,类似于 Java 自带的 Executor 系列 API 或者 Android 的 Handler 系列 API。

只不过呢,协程它不仅提供了方便的 API,在设计思想上是一个基于线程的上层框架,你可以理解为新造了一些概念用来帮助你更好地使用这些 API,仅此而已。

就像 ReactiveX 一样,为了让你更好地使用各种操作符 API,新造了 Observable 等概念。

说到这里,Kotlin 协程的三大疑问:协程是什么、挂起是什么、挂起的非阻塞式是怎么回事,就已经全部讲完了。非常简单:

协程就是切线程;
挂起就是可以自动切回来的切线程;
挂起的非阻塞式指的是它能用看起来阻塞的代码写出非阻塞的操作,就这么简单。
当然了,这几句是总结,它们背后的原理你是一定要掌握住的。如果忘了,再去把之前的视频和文章看一遍就好。

视频中还纠正了官方文档里面的一个错误,这里就不再重复了,最后想表达一点:

Kotlin 协程并没有脱离 Kotlin 或者 JVM 创造新的东西,它只是将多线程的开发变得更简单了,可以说是因为 Kotlin 的诞生而顺其自然出现的东西,从语法上看它很神奇,但从原理上讲,它并不是魔术。

最后

转自:到底什么是「非阻塞式」挂起?协程真的更轻量级吗?

相关文章

  • Kotlin - 协程中的那些关键点

    ### 写在前面 1.协程“非阻塞式挂起” 你真的弄懂了吗? 2.协程suspend关键字到底有多神奇? 3.协程...

  • 协程(2)-到底什么是「非阻塞式」挂起?协程真的更轻量级吗?

    什么是「非阻塞式挂起」 非阻塞式是相对阻塞式而言的。 编程语言中的很多概念其实都来源于生活,就像脱口秀的段子一样。...

  • 破解 Kotlin 协程(6) - 协程挂起篇

    关键词:Kotlin 协程 协程挂起 任务挂起 suspend 非阻塞 协程的挂起最初是一个很神秘的东西,因为我们...

  • Kotlin协程

    协程是什么? 协程本质是Kotlin官方提供的线程API(本质就是一个线程框架)最基本的功能是并发非阻塞式挂起 ...

  • kotlin协程

    协程基础 轻量级线程。在一个线程中可以启动多个协程。 在协程中使用同步方式写出异步代码(协程挂起时不会阻塞线程),...

  • 八,Kotlin协程详解

    概念 Kotlin协程是一个异步框架,是建立在线程基础上轻量级的线程.协程依赖于线程,但是协程挂起时不需要阻塞线程...

  • 1.协程的基本实现

    协程是什么?协程是一种非抢占式或者说协作式的计算机程序并发调度的实现,程序可以主动挂起或者恢复执行,本质上,协程是...

  • 【手撕代码】Python协程实现生产者消费者模型

    什么是协程? 协程是一种用户态的轻量级线程,协程的调度完全由用户控制。 协程的实现为协作式而非抢占式的,这是和进程...

  • kotlin协程的使用与原理

    协程 协程是轻量级线程,一个线程中可以有很多协程,协程本质上可以认为是运行在线程上的代码块,协程提供的挂起操作会使...

  • Kotlin 协程

    协程 协程就像非常轻量级的线程。线程是由系统调度的,线程切换或线程阻塞的开销都比较大。而协程依赖于线程,但是协程挂...

网友评论

    本文标题:协程(2)-到底什么是「非阻塞式」挂起?协程真的更轻量级吗?

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