從硬件角度去理解協(xié)程

son

2022年,虎年虎虎生威~!

前言

Android 開發(fā)者來說 Kotlin 語言已經(jīng)是很熟悉的了,但 Kotlin 中的 協(xié)程 不了解的同學(xué)可能還有很多。

閱讀網(wǎng)絡(luò)上大多數(shù)文章得到的關(guān)于 協(xié)程 幾個關(guān)鍵詞:

  • 像是線程;
  • 不是線程;
  • 用戶態(tài);
  • 協(xié)作式;

感覺很懵逼,我就問一個 協(xié)程 而已為什么出現(xiàn)這么多奇奇怪該的名詞。

協(xié)程簡介

維基百科:協(xié)程

協(xié)程(英語:coroutine)是計算機程序的一類組件,推廣了協(xié)作式多任務(wù)的子例程,允許執(zhí)行被掛起與被恢復(fù)。 相對子例程而言,協(xié)程更為一般和靈活,但在實踐中使用沒有子例程那樣廣泛。 協(xié)程更適合于用來實現(xiàn)彼此熟悉的程序組件,如協(xié)作式多任務(wù)、異常處理、事件循環(huán)、迭代器、無限列表和管道。

電腦物理硬件

協(xié)程 之前我們先聊一下計算機硬件相關(guān)的知識。

物理 cpu 數(shù)

指主板上實際插入的 cpu 硬件個數(shù)(socket)。(但是這一概念經(jīng)常被泛泛的說成是 cpu 數(shù),這很容易導(dǎo)致與 core 數(shù),processor 數(shù)等概念混淆,所以此處強調(diào)是物理 cpu 數(shù))。

由于在主板上引入多個 cpu 插槽需要更復(fù)雜的硬件支持(連接不同插槽的 cpu 到內(nèi)存和其他資源),通常只會在服務(wù)器上才這樣做。在家用電腦中,一般主板上只會有一個 cpu 插槽。

核數(shù)

一開始,每個物理 cpu 上只有一個核心 a single core ,對操作系統(tǒng)而言,也就是同一時刻只能運行一個進程/線程。 為了提高性能,cpu 廠商開始在單個物理 cpu 上增加核心(實實在在的硬件存在),也就出現(xiàn)了雙核心 cpudual-core cpu)以及多核心 cpumultiple cores),這樣一個雙核心 cpu 就是同一時刻能夠運行兩個進程/線程的。

超線程技術(shù)

同時多線程技術(shù)(simultaneous multithreading)

超線程技術(shù)(hyper–threading/HT)

本質(zhì)一樣,是為了提高單個 core 同一時刻能夠執(zhí)行的多線程數(shù)的技術(shù)(充分利用單個 core 的計算能力,盡量讓其“一刻也不得閑”)。

simultaneous multithreading 縮寫是 SMTAMD 和其他 cpu 廠商的稱呼。 hyper–threadingIntel 的稱呼,可以認為 hyper–threadingSMT 的一種具體技術(shù)實現(xiàn)。

AMD-R7
Intel-i7

所以可以這樣說:某款采用 SMT 技術(shù)的 4核心 AMD cpu 提供了 8線程 同時執(zhí)行的能力;某款采用 HT 技術(shù)的 2 核心 Intel cpu 提供了 4 線程 同時執(zhí)行的能力。

總的邏輯 cpu 數(shù) = 物理 cpu 數(shù) * 每顆物理 cpu 的核心數(shù) * 每個核心的超線程數(shù)

線程和協(xié)程

協(xié)程 的時候絕對不能不提 線程 。

線程 是操作系統(tǒng)能夠進行運算的最小單位。

在之前一般情況下 CPU 的每個核心同一時間只能執(zhí)行一個線程,除了現(xiàn)在比較新的 CPU 擁有上面說的使用 SMT 或者 HT 技術(shù)。

CPU 的核心數(shù)和 線程 的個數(shù)沒有必然關(guān)系。舉個很簡單的例子,我一段代碼可以一直創(chuàng)建100個線程

CPU 根本不理解自己執(zhí)行的指令屬于哪個 線程,CPU 也不需要理解這些,它只需只需當(dāng)前操作系統(tǒng)給它分配的指令就行。

在單核 CPU 時代所有的多線程其實都是多任務(wù),多個任務(wù)交替使用 CPU資源 。

有了多核之后,運行在兩個線程的任務(wù)才實現(xiàn)正真的并行,但電腦的實際核數(shù)永遠也達不到我們運算需要的任務(wù)數(shù)量。所以多個任務(wù)交替使用 CPU資源 這種情況一直存在,但我們知道 CPP 切換執(zhí)行線程的上下文都是需要消耗資源的,任務(wù)數(shù)量越多不一定執(zhí)行效率更高。對于計算密集型的程序有的建議是設(shè)置線程的最佳數(shù)量為 CPU 可執(zhí)行線程數(shù)的 1.5倍 或者 1倍+1

在這個時候我們想到能不能在異步任務(wù)之間切換的時候不切換 CPU 的上下文狀態(tài),這樣可以減少很多資源的浪費?;蛘咴?CPU 長時間執(zhí)行 I/O操作 的時候讓其他例程先執(zhí)行,提供資源的利用率。

協(xié)程 就在這個時候產(chǎn)生了,協(xié)作式執(zhí)行多任務(wù)的子例程。

這時候我們已經(jīng)對 協(xié)程 有了初步的了解了,回頭想想文章開頭4個描述 協(xié)程 的說明。

  • 像是線程:在部分程序執(zhí)行的過程中,協(xié)程的并發(fā)執(zhí)行就是利用的多線程技術(shù)(例如:沒有進行改版的 Java程序 )。所以說它像是線程;
  • 不是線程:并發(fā)任務(wù)的調(diào)度不是都通過操作系統(tǒng)級別線程切換執(zhí)行,而是程序本身支持單個線程的多個并發(fā)任務(wù)。所以也可以說它不是線程,可以叫它們纖程 Fiber ,或者綠色線程 GreenThread 。正如一個進程可以擁有多個線程一樣,一個線程也可以擁有多個協(xié)程。
  • 用戶態(tài):不是系統(tǒng)級別的線程而且能自主執(zhí)行異步任務(wù),這種由程序員自己寫程序來管理的輕量級線程叫做用戶空間線程,具有對內(nèi)核來說不可見的特性。
  • 協(xié)作式:要求每個運行中的程序,定位放棄自己的執(zhí)行權(quán)利,讓多個任務(wù)一起交替執(zhí)行。維基百科:協(xié)作式多任務(wù);

Android中的協(xié)程

上面說的 協(xié)程 減少上下文切換,提供效率,那么 Androidkotlin 支持協(xié)程么?

kotlin 官方文檔說:本質(zhì)上,協(xié)程是輕量級的線程。

但就目前 Kotlin-JVM 而言來說 協(xié)程 它就是線程。其本質(zhì)上還是一套基于原生 Java Thread API 的封裝。

可能后續(xù) Kotlin 的版本會有正真的協(xié)程相關(guān)的機制來代替線程。

這個時候可能我們可能就有一些疑問,既然 協(xié)程Android 平臺上依舊是 線程 并沒有提示運行效率,Java 中的 ExecutorAndroid 中的 AsyncTask 都能提供并發(fā)任務(wù),那么 kotlin協(xié)程 它有什么用?后面會有一篇文章單獨講解~!

參考資料:

一文讀懂什么是進程、線程、協(xié)程

Kotlin 協(xié)程真的比 Java 線程更高效嗎?

扔物線:Kotlin的協(xié)程用例瞥一眼

文章到這里就全部講述完啦,若有其他需要交流的可以留言哦~!~!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容