这是面试交流群中,群友问的一个问题。为什么 kotlin 使用协程?
这是一个非常好的问题,我们都知道协程好,那么协程相比于线程好在哪里呢,这篇文章我们一起聊聊,kotlin 使用协程的原因。
低内存开销
协程的内存开销非常低。与线程相比,协程只需要少量的内存来维护其状态和堆栈。
一个线程通常需要分配 1MB 左右的堆栈空间,如果是 300 个线程就需要 300MB 左右的虚拟内存。
而一个协程的堆栈则是动态增长的,初始分配的内存非常小,通常在 2KB 左右,整整差了 500 倍,这也是为什么说协程是轻量级的。
高并发性
由于协程的轻量级特性,一个应用程序可以同时运行大量的协程,从而实现高并发性。协程的调度是由程序控制的,可以在一个线程上高效地执行多个协程。
而线程的数量受限于系统资源,一个线程初始栈大小就有 1MB,300 个线程就需要 300MB 左右的虚拟内存,开的越多越很容易出现 OOM。
所以当涉及到大量并发的时候,使用协程性能更好。
这里可能很多人会有疑问,怎么会有 APP 创建这么多线程?
这是真实存在的,比如航母级应用微信、QQ、抖音、快手,这类软件创建 300 个线程很常见。
无锁机制
说到并发编程,不得不说并发安全,线程一般是通过锁来保证并发安全的,实现起来比较复杂,容易出现死锁的情况,也会增加上下文切换的开销。
协程切换通常不需要使用锁机制,因为协程在单线程环境中运行时不会出现竞争条件。
低上下文切换开销
协程的上下文切换开销非常低。协程切换是在用户空间进行的,不涉及操作系统内核的调度。这意味着切换协程时无需进行系统调用,从而减少了进入和退出内核态的开销,而线程切换涉及到内核态和用户态的转换,开销比较大。
协程的上下文切换只需保存和恢复少量的状态信息,如程序计数器、少量寄存器和堆栈指针。线程切换则需要保存和恢复更多的状态信息,包括所有寄存器、线程堆栈、线程局部存储等,导致上下文切换开销较高。
快速创建和销毁
协程的创建和销毁速度非常快。创建一个协程的开销仅仅是分配一小段内存初始化其状态,而线程的创建需要操作系统分配资源,初始化线程上下文等复杂操作,耗时较长。
非阻塞的执行模型
协程采用非阻塞的执行模型。它们可以挂起自身而不阻塞线程,从而避免了线程阻塞带来的资源浪费和性能问题。协程挂起时,其他协程可以继续执行,从而提高了资源利用率和响应速度。
简化了异步编程
协程简化了异步编程。传统的异步编程需要使用回调、Future 等复杂的机制,而协程通过挂起和恢复机制,使得异步代码可以像同步代码一样编写,减少了代码复杂度和错误率。
Hi 大家好,我是 DHL,大厂程序员,公众号:ByteCode ,在美团、快手、小米工作过。搞过逆向,做过性能优化,研究过系统,擅长鸿蒙、Android、Kotlin、性能优化、职场分享。