2022年栽燕,虎年虎虎生威~罕袋!
前言
Android
開發(fā)者來說 Kotlin
語言已經(jīng)是很熟悉的了,但 Kotlin
中的 協(xié)程
不了解的同學可能還有很多碍岔。
閱讀網(wǎng)絡上大多數(shù)文章得到的關于 協(xié)程
幾個關鍵詞:
- 像是線程浴讯;
- 不是線程;
- 用戶態(tài)蔼啦;
- 協(xié)作式榆纽;
感覺很懵逼,我就問一個 協(xié)程
而已為什么出現(xiàn)這么多奇奇怪該的名詞捏肢。
協(xié)程簡介
協(xié)程(英語:coroutine)
是計算機程序的一類組件奈籽,推廣了協(xié)作式多任務的子例程,允許執(zhí)行被掛起與被恢復鸵赫。 相對子例程而言衣屏,協(xié)程更為一般和靈活,但在實踐中使用沒有子例程那樣廣泛奉瘤。 協(xié)程更適合于用來實現(xiàn)彼此熟悉的程序組件勾拉,如協(xié)作式多任務、異常處理盗温、事件循環(huán)藕赞、迭代器、無限列表和管道卖局。
電腦物理硬件
說 協(xié)程
之前我們先聊一下計算機硬件相關的知識斧蜕。
物理 cpu 數(shù)
指主板上實際插入的 cpu
硬件個數(shù)(socket
)。(但是這一概念經(jīng)常被泛泛的說成是 cpu
數(shù)砚偶,這很容易導致與 core
數(shù)批销,processor
數(shù)等概念混淆洒闸,所以此處強調(diào)是物理 cpu
數(shù))。
由于在主板上引入多個 cpu
插槽需要更復雜的硬件支持(連接不同插槽的 cpu
到內(nèi)存和其他資源)均芽,通常只會在服務器上才這樣做丘逸。在家用電腦中,一般主板上只會有一個 cpu
插槽掀宋。
核數(shù)
一開始深纲,每個物理 cpu
上只有一個核心 a single core
,對操作系統(tǒng)而言劲妙,也就是同一時刻只能運行一個進程/線程湃鹊。 為了提高性能,cpu
廠商開始在單個物理 cpu
上增加核心(實實在在的硬件存在)镣奋,也就出現(xiàn)了雙核心 cpu
(dual-core cpu
)以及多核心 cpu
(multiple cores
)币呵,這樣一個雙核心 cpu
就是同一時刻能夠運行兩個進程/線程的。
超線程技術
同時多線程技術(simultaneous multithreading)
超線程技術(hyper–threading/HT)
本質(zhì)一樣侨颈,是為了提高單個 core
同一時刻能夠執(zhí)行的多線程數(shù)的技術(充分利用單個 core
的計算能力余赢,盡量讓其“一刻也不得閑”)。
simultaneous multithreading
縮寫是 SMT
肛搬,AMD
和其他 cpu
廠商的稱呼没佑。 hyper–threading
是 Intel
的稱呼毕贼,可以認為 hyper–threading
是 SMT
的一種具體技術實現(xiàn)温赔。
所以可以這樣說:某款采用 SMT
技術的 4核心
AMD cpu
提供了 8線程
同時執(zhí)行的能力;某款采用 HT
技術的 2 核心
Intel cpu
提供了 4 線程
同時執(zhí)行的能力鬼癣。
總的邏輯
cpu
數(shù) = 物理cpu
數(shù) * 每顆物理cpu
的核心數(shù) * 每個核心的超線程數(shù)
線程和協(xié)程
講 協(xié)程
的時候絕對不能不提 線程
陶贼。
線程
是操作系統(tǒng)能夠進行運算的最小單位。
在之前一般情況下 CPU
的每個核心同一時間只能執(zhí)行一個線程待秃,除了現(xiàn)在比較新的 CPU
擁有上面說的使用 SMT
或者 HT
技術拜秧。
但 CPU
的核心數(shù)和 線程
的個數(shù)沒有必然關系。舉個很簡單的例子章郁,我一段代碼可以一直創(chuàng)建100個線程枉氮。
CPU
根本不理解自己執(zhí)行的指令屬于哪個 線程
,CPU
也不需要理解這些暖庄,它只需只需當前操作系統(tǒng)給它分配的指令就行聊替。
在單核 CPU
時代所有的多線程其實都是多任務,多個任務交替使用 CPU資源
培廓。
有了多核之后惹悄,運行在兩個線程的任務才實現(xiàn)正真的并行,但電腦的實際核數(shù)永遠也達不到我們運算需要的任務數(shù)量肩钠。所以多個任務交替使用 CPU資源
這種情況一直存在泣港,但我們知道 CPP
切換執(zhí)行線程的上下文都是需要消耗資源的暂殖,任務數(shù)量越多不一定執(zhí)行效率更高。對于計算密集型的程序有的建議是設置線程的最佳數(shù)量為 CPU
可執(zhí)行線程數(shù)的 1.5倍
或者 1倍+1
当纱。
在這個時候我們想到能不能在異步任務之間切換的時候不切換 CPU
的上下文狀態(tài)呛每,這樣可以減少很多資源的浪費∑侣龋或者在 CPU
長時間執(zhí)行 I/O操作
的時候讓其他例程先執(zhí)行莉给,提供資源的利用率。
協(xié)程
就在這個時候產(chǎn)生了廉沮,協(xié)作式執(zhí)行多任務的子例程颓遏。
這時候我們已經(jīng)對 協(xié)程
有了初步的了解了,回頭想想文章開頭4個描述 協(xié)程
的說明滞时。
- 像是線程:在部分程序執(zhí)行的過程中叁幢,協(xié)程的并發(fā)執(zhí)行就是利用的多線程技術(例如:沒有進行改版的
Java程序
)。所以說它像是線程坪稽; - 不是線程:并發(fā)任務的調(diào)度不是都通過操作系統(tǒng)級別線程切換執(zhí)行曼玩,而是程序本身支持單個線程的多個并發(fā)任務。所以也可以說它不是線程窒百,可以叫它們纖程
Fiber
黍判,或者綠色線程GreenThread
。正如一個進程可以擁有多個線程一樣篙梢,一個線程也可以擁有多個協(xié)程顷帖。 - 用戶態(tài):不是系統(tǒng)級別的線程而且能自主執(zhí)行異步任務,這種由程序員自己寫程序來管理的輕量級線程叫做用戶空間線程渤滞,具有對內(nèi)核來說不可見的特性贬墩。
- 協(xié)作式:要求每個運行中的程序,定位放棄自己的執(zhí)行權利妄呕,讓多個任務一起交替執(zhí)行陶舞。維基百科:協(xié)作式多任務;
Android中的協(xié)程
上面說的 協(xié)程
減少上下文切換绪励,提供效率肿孵,那么 Android
的 kotlin
支持協(xié)程么?
kotlin
官方文檔說:本質(zhì)上,協(xié)程是輕量級的線程疏魏。
但就目前 Kotlin-JVM
而言來說 協(xié)程
它就是線程停做。其本質(zhì)上還是一套基于原生 Java Thread API
的封裝。
可能后續(xù) Kotlin
的版本會有正真的協(xié)程相關的機制來代替線程蠢护。
這個時候可能我們可能就有一些疑問雅宾,既然 協(xié)程
在 Android
平臺上依舊是 線程
并沒有提示運行效率,Java
中的 Executor
和 Android
中的 AsyncTask
都能提供并發(fā)任務,那么 kotlin
的 協(xié)程
它有什么用眉抬?后面會有一篇文章單獨講解~贯吓!
參考資料:
Kotlin 協(xié)程真的比 Java 線程更高效嗎?
文章到這里就全部講述完啦悄谐,若有其他需要交流的可以留言哦~!~库北!