成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聽大佬聊聊Kotlin中把碼仔玩死的:協程

開發 后端
本文講的協程主要以kotlin為主,同時可能參考python,go,但是會盡量避免使用代碼,而是嘗試用通俗的語言來聊協程的發展歷程,盡量保證大家都能理解。

 [[315495]]

前言

本文講的協程主要以kotlin為主,同時可能參考python,go,但是會盡量避免使用代碼,而是嘗試用通俗的語言來聊協程的發展歷程,盡量保證大家都能理解。

近些年,一些編程語言的新貴Go和Kotlin紛紛引入了協程這個語言特性,使得協程這個似乎十分陌生的概念開始頻繁進入大家的視野,為了便于理解,開發者們都把它當作線程的小弟來對待,即輕量級線程。可是真要細說起來,協程其實是很早就出現的一個編程概念,它的出現甚至是是早于線程的,但是就編程語言的江湖地位而言,協程是不如線程的,所以向線程低頭叫爸爸不奇怪。

[[315496]]

看了我上面的介紹,大家一定很納悶,你說協程出現早,有資歷,那為啥幾十年的編程語言發展下來就就混成了這副咸魚樣?線程出現晚,但怎么就一棵星星之火點著了編程語言的草原。成為了編程語言中的重要概念呢??再者,協程幾十年的咸魚一條,到如今怎么突然有了夢想,翻身把歌唱的呢?

今天就和大家一起來梳理一下協程的整個發展歷程,希望能幫助大家更加理解協程。

協程的出現

咱們先來說說協程的歷史,以及它是怎么混的這么慘的,畢竟悲催的人生都需要一個解釋。

協程最早誕生于1958年,被應用于匯編語言中(距今已有60多年了),對它的完整定義發表于1963 年,協程是一種通過代碼執行的恢復與暫停來實現協作式的多任務的程序組件。

而與此同時,線程的出現則要晚一些,伴隨著操作系統的出現,線程大概在1967年被提出。線程作為由操作系統調度最小執行組件,主要用于實現搶占式的多任務。

既然大家都搞多任務,按說誰也不能比誰強多少啊,況且協程還早生幾年,理論上通過自身努力發展,在編程語言中占據核心地位是極有可能的。

[[315497]]

但是這協程的發展啊,一方面當然要靠自我奮斗,另一方面,也要考慮歷史進程。而上個世紀七八九十年代,是計算機瘋狂朝著小型化和個人化的方向演進的時代,計算機非常依賴操作系統來提供用戶交互和壓榨CPU的最大性能,而操作系統怎么來壓榨計算機性能的呢?靠多線程。操作系統跟隨個人計算機的普及之后,編程語言自然也開始依賴操作系統提供的接口來駕馭計算機了,線程成了幾乎所有編程語言跳不過的一個重要概念,并一直延續至今。

到這里你可能要問了,大家都是搞多任務的,為什么線程能提升cpu的資源利用率,協程不能呢?

當然有很多其他的原因能解釋,但最本質的原因仍然是協程和線程是有顯著區別的兩個概念,到這里我們就要回過頭來聊聊什么叫協作式多任務,什么叫搶占式多任務?以及這兩種任務是否是同一種概念?

  • 協作式多任務:

上圖是一個壽司生產的部分工序,我們可以把圖中的傳送轉盤和機器抓手可視作兩個任務,一起協作完成了食物的生產。這就是協作式多任務。協作式的多任務要求任務之間相互熟悉,才能實現協作。

  • 搶占式多任務:

喂金魚的場景,一把飼料下去,所有金魚馬上圍上來一搶而空,這里每個金魚都相當于一個任務線程,這就是搶占式多任務。而搶占式多任務(線程)之間不需要了解和配合,只有競爭關系。

上面兩張圖,比較生動的展示了協作式多任務(協程)和搶占式多任務(多線程)之間的區別。我們能夠發現,協程更加適合那些相互熟悉的任務組件通過密切配合協作完成某些工作,協作式多任務里的“任務”是一種子程序(可稱為函數)。搶占式多任務里的任務則是指能搶占資源的組件或代碼(其實就是線程),這里的多任務也就是多線程。所以說,協程和線程本來是差異非常大的兩種概念,他們的能力是不同的,而線程的這種能力正好迎合了那個時代的需求。自我奮斗+歷史進程是線程成功的主要原因。

當然,在另一方面,也由于協程是基于編程語言層面的一種概念,它并沒有統一定義的接口,因此在不同的語言中實現后的效果是不同的,這也會對開發者造成極大的困擾,不利于它的推廣。而反觀線程,通過操作系統的統一接口,定義了大體相同的線程使用方式,保證了不同的編程語言都對線程的使用是大體一致。

講到這里,我們來總結下協程早期發展不順的原因:

  1. 協程沒有代表先進生產力的發展要求,先進文化的前進方向,和最廣大開發者的根本利益[手動狗頭]。
  2. 協程在不同編程語言中,它的實際表現有差異,非常不利于開發者的理解和使用。

以上兩點,就是協程幾十年以來一直不溫不火的原因。我們也看到,雖然看起來都在搞多任務,但是協程和線程實際是沒有太多交集的。

咸魚翻身

雖說協程這種協作式多任務的組件不能提高程序執行的效率,似乎沒有太廣泛的應用前景,但這協程吶,也不能隨意否定自己,因為不知道什么時候,你就突然被歷史進程給關照了。

還是從線程說起,雖然線程成為編程世界的重要概念,但是在多年的使用過程中開發者們也逐漸意識到了它的痛點:

  • 線程之間(異步代碼)難以交互難度比較大,往往只能用callback,大量的callback會代碼難以閱讀和理解,最終讓項目變得難以維護。

簡單說就是在開發者端,線程之間如何更方便的交互。

而這里協程能做什么呢?

或許我再重新表達一下線程的痛點:在開發者端,線程之間如何更方便的協作。

回想一下,我們是怎么介紹協程的?協作式多任務對吧,還記得上圖中的轉盤和機器抓手的協作么?我們當時說這兩個任務更像是兩個函數的協作,但如果把轉盤和機器抓手視作兩個線程呢?借助編譯器,把線程封裝成一個個能暫停和恢復的函數,線程是不是就可以像協程設計的那樣協作呢?

我們還是從代碼層面來看看如今協程是如何被使用的吧。設計一個簡單的需求:社區內用戶進行發帖時,需要先從后臺驗證發帖權限,請求兩個接口,那么可能我們需要嘗試開啟兩個線程先后來完成。

  • 普通的callback代碼:
  1. fun tryPost(){ 
  2.     // 先通過接口驗證權限 (實際開啟了一個線程,然后等待回調) 
  3.     findUserPermission(user,callback()){ 
  4.         public void onSuccess(UserPermission response){ 
  5.             // 回調 如果成功 ,檢查是否有權限 
  6.             if(response.hasPermission){ 
  7.             // 如果有權限,則訪問發帖接口 (同樣開啟線程,等待回調) 
  8.                 postContent(content,callback()){ 
  9.                     public void onSuccess(Result response){ 
  10.                         // handle successful response 
  11.                     } 
  12.                     public void onFail(){ 
  13.                          
  14.                     } 
  15.                 } 
  16.             }else
  17.                 // 如果無權限,則...... 
  18.             } 
  19.         } 
  20.          
  21.         public void onFail(){  
  22.         } 
  23.     } 

這是比較常見的做法,我們需要訪問兩次接口,而交互只能在callback中進行,但是其實代碼已經很難看了,如果還有其他的邏輯的話,那代碼只會更加冗雜,難以維護。

那協程是怎么解決這種痛點的呢?我們看看(kotlin和python)協程的代碼如何實現這種需求:

  • kotlin的協程代碼
  1. // 函數通過suspend關鍵字標識,可以被協程調用,具備暫停恢復的能力 ,實際上仍然使用了io線程來完成接口請求 
  2. suspend fun tryfindUserPermission():PermissionResponse { 
  3.     return withContext(Dispatchers.IO){ 
  4.         findUserPermission(user
  5.     } 
  6. } 
  7.  
  8. // 函數通過suspend關鍵字標識,可以被協程調用 
  9. suspend fun post():Result { 
  10.     return  withContext(Dispatchers.IO) { 
  11.         postContent(content) 
  12.     } 
  13. } 
  14.      
  15. fun tryPost(){ 
  16.     //啟動一個協程 
  17.      launch{ 
  18.      //代碼執行到這一行,讓出cpu,進入暫停狀態,等待請求成功之后,會恢復執行) 
  19.      var response = tryfindUserPermission()    // 向后端訪問用戶權限 
  20.      if(response.hasPermission){ 
  21.      // 有權限則開始發帖 (開啟線程,讓出cpu,暫停執行,等待恢復) 
  22.         var response =  post() 
  23.          // handle response if need 
  24.     } 
  25.   } 

可以看到,在kotlin中,協程通過把線程里的代碼封裝成一種能暫停/恢復的函數,讓多線程之間的交互就像普通的函數一樣簡單,不需要callback。

  • python的協程代碼
  1. import asyncio 
  2. // async 的關鍵字,表明這個函數可以被協程調用 
  3. async def findUserPermission(): 
  4.     // handle http request 
  5.     ... 
  6.     ... 
  7.     return response 
  8. async def postContent(): 
  9.     // handle http request 
  10.     ... 
  11.     ... 
  12.     return response 
  13.      
  14. async def main(): 
  15. // 嘗試獲取權限信息 同樣會讓出cpu,進入暫停狀態,等待恢復 
  16.     reponse = await findUserPermission() 
  17.     // 判斷有權限的情況下,進行發帖 
  18.     if response.hasPermission : 
  19.         res = await postContent() 
  20.         // handle response if need 
  21. asyncio.run(main()) 

python通過協程處理這種問題本質和kotlin是一致的。

相信大家也能看到,協程在不同的語言中的表現方式是有差異的

通過上面幾段偽代碼,我們能夠比較清楚看到,協程能非常明顯的簡化了線程之間協作復雜度,讓我們可以以編寫同步代碼的方式來編寫異步代碼,極大的簡化你的邏輯,讓你的代碼容易維護。

那么協程是如何做到的呢?

雖然不同的語言中,協程有所差異,但是原理都差不多,編程語言的編譯器通過一些關鍵字(kotlin中用suspend,python中用async等)來修飾函數,在編譯期間根據關鍵字生成一些線程相關的代碼來實現函數的暫停恢復的功能,從而實現把線程相關的代碼留在編譯期間產生,在開發層面就能提供像普通函數一般的協作方式。

因為解決了這個痛點,協程開始變得越來越受開發者歡迎。而協程通過編譯器的幫助把線程相關的代碼留在了編譯期間產生,開發者可以通過操作協程就可以達到使用線程的目的,所以現在大家認為協程是一種輕量級的線程。

對于多線程的協作,或者說異步代碼之間的協作并不是只有協程一家解決方案,在JS中,有promise,Java中有RxJava等等,他們都致力于解決異步編程的相關問題,希望能以編寫同步代碼的方式來寫異步代碼,目前來看,他們都做的很不錯。

總結

大家對于協程的理解有很多分歧,但是對我而言,協程其實得分兩個階段來理解:

  • 在協程誕生之初,只是用來解決編程中的某些特殊問題的編程組件,它的多任務更像多個函數的組合協作執行,那個時候,協程其實更像是一種具備暫停恢復的函數。但是這種功能似乎并不受歡迎,因此協程在很長一段時間內都是比較小眾的。(此時協程和線程關系并不大)
  • 如今它成為底層支持多線程的協作式多任務組件,很好的解決了線程協作的痛點,同時也逐漸變得越來越受歡迎,協程和線程的關系更加親密,它們似乎也變得更加相似。(如今你可以把協程視作一種輕量級線程)

而協程的發展歷程,其實也就是經歷了這兩個階段。

 

責任編輯:武曉燕 來源: 碼個蛋
相關推薦

2023-10-24 19:37:34

協程Java

2023-08-08 07:18:17

協程管道函數

2020-06-19 08:01:48

Kotlin 協程編程

2021-05-20 09:14:09

Kotlin協程掛起和恢復

2025-05-16 08:21:45

2019-10-23 14:34:15

KotlinAndroid協程

2021-09-16 09:59:13

PythonJavaScript代碼

2021-04-28 09:08:23

Kotlin協程代碼

2022-11-21 06:55:08

golang協程

2023-11-17 11:36:59

協程纖程操作系統

2023-11-29 07:10:50

python協程異步編程

2020-02-24 10:39:55

Python函數線程池

2024-02-05 09:06:25

Python協程Asyncio庫

2025-04-27 08:23:38

Kotlin協程管理

2025-06-26 04:10:00

2024-06-27 07:56:49

2023-09-03 19:13:29

AndroidKotlin

2023-11-26 18:35:25

Python編程語言

2020-07-07 10:03:27

Android 協程開發

2020-07-09 10:03:07

Android 協程開發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产小视频在线 | 欧美一区二区三区在线观看 | 久久久性| 91精品久久久 | 国产夜恋视频在线观看 | 日韩成人在线观看 | 日韩欧美三区 | 亚洲人成人一区二区在线观看 | 国产精品爱久久久久久久 | 精品国产91 | 日韩精品在线看 | 日韩在线中文字幕 | 亚洲精品自在在线观看 | 观看毛片 | 一区二区久久精品 | 欧美一区在线视频 | 久久久久国产 | 91黄色免费看 | 韩日一区二区 | 2018中文字幕第一页 | 99re在线视频 | 欧美视频在线观看 | 色视频www在线播放国产人成 | 丝袜 亚洲 另类 欧美 综合 | 99在线免费视频 | 国产精品一区二区久久 | 欧美三级久久久 | 久久精品二区 | 自拍在线 | 精品国产一区二区三区性色av | 日本三级网站在线观看 | 色噜噜色综合 | 免费看a | 免费观看一级特黄欧美大片 | 亚洲性视频网站 | 久久五月婷 | 狠狠婷婷综合久久久久久妖精 | 久久亚洲精品国产精品紫薇 | 夜夜爽99久久国产综合精品女不卡 | 精品无码久久久久久国产 | 欧美午夜视频 |