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

Python 協(xié)程與 JavaScript 協(xié)程的對比

開發(fā) 后端
以前沒怎么接觸前端,對 JavaScript 的異步操作不了解,現(xiàn)在有了點了解。一查發(fā)現(xiàn) Python 和 JavaScript 的協(xié)程發(fā)展史簡直就是一毛一樣!這里大致做下橫向?qū)Ρ群涂偨Y(jié),便于對這兩個語言有興趣的新人理解和吸收。

[[424288]]

 前言

以前沒怎么接觸前端,對 JavaScript 的異步操作不了解,現(xiàn)在有了點了解。一查發(fā)現(xiàn) Python 和 JavaScript 的協(xié)程發(fā)展史簡直就是一毛一樣!

這里大致做下橫向?qū)Ρ群涂偨Y(jié),便于對這兩個語言有興趣的新人理解和吸收。

共同訴求

  •  隨著 cpu 多核化,都需要實現(xiàn)由于自身歷史原因(單線程環(huán)境)下的并發(fā)功能
  •  簡化代碼,避免回調(diào)地獄,關(guān)鍵字支持
  •  有效利用操作系統(tǒng)資源和硬件:協(xié)程相比線程,占用資源更少,上下文更快

什么是協(xié)程?

總結(jié)一句話,協(xié)程就是滿足下面條件的函數(shù):

  •  可以暫停執(zhí)行(暫停的表達式稱為暫停點)
  •  可以從掛起點恢復(fù)(保留其原始參數(shù)和局部變量)
  •  事件循環(huán)是異步編程的底層基石

混亂的歷史

Python 協(xié)程的進化

  •  Python2.2 中,第一次引入了生成器
  •  Python2.5 中,yield 關(guān)鍵字被加入到語法中
  •  Python3.4 時有了 yield from(yield from 約等于 yield + 異常處理 + send), 并試驗性引入的異步 I/O 框架 asyncio(PEP 3156)
  •  Python3.5 中新增了 async/await 語法(PEP 492)
  •  Python3.6 中 asyncio 庫"轉(zhuǎn)正" (之后的官方文檔就清晰了很多)

在主線發(fā)展過程中,也出現(xiàn)了很多支線的協(xié)程實現(xiàn)如 Gevent。 

  1. def foo():  
  2.     print("foo start")  
  3.     a = yield 1  
  4.     print("foo a", a)  
  5.     yield 2  
  6.     yield 3  
  7.     print("foo end")  
  8. gen = foo()  
  9. # print(gen.next())  
  10. # gen.send("a")  
  11. # print(gen.next())  
  12. # print(foo().next())  
  13. # print(foo().next())  
  14. # 在python3.x版本中,python2.x的g.next()函數(shù)已經(jīng)更名為g.__next__(),使用next(g)也能達到相同效果。  
  15. # next()跟send()不同的地方是,next()只能以None作為參數(shù)傳遞,而send()可以傳遞yield的值.  
  16. print(next(gen))  
  17. print(gen.send("a"))  
  18. print(next(gen))  
  19. print(next(foo()))  
  20. print(next(foo()))  
  21. list(foo())  
  22. """  
  23. foo start  
  24.  
  25. foo a a  
  26.  
  27.  
  28. foo start  
  29.  
  30. foo start  
  31.  
  32. foo start  
  33. foo a None  
  34. foo end  
  35. """ 

JavaScript 協(xié)程的進化

  •  同步代碼
  •  異步 JavaScript: callback hell
  •  ES6 引入 Promise/a+, 生成器 Generators(語法 function foo(){}* 可以賦予函數(shù)執(zhí)行暫停/保存上下文/恢復(fù)執(zhí)行狀態(tài)的功能), 新關(guān)鍵詞 yield 使生成器函數(shù)暫停。
  •  ES7 引入 async函數(shù)/await語法糖,async 可以聲明一個異步函數(shù)(將 Generator 函數(shù)和自動執(zhí)行器,包裝在一個函數(shù)里),此函數(shù)需要返回一個 Promise 對象。await 可以等待一個 Promise 對象 resolve,并拿到結(jié)果

Promise 中也利用了回調(diào)函數(shù)。在 then 和 catch 方法中都傳入了一個回調(diào)函數(shù),分別在 Promise 被滿足和被拒絕時執(zhí)行,這樣就就能讓它能夠被鏈接起來完成一系列任務(wù)。

總之就是把層層嵌套的 callback 變成 .then().then()...,從而使代碼編寫和閱讀更直觀。

生成器 Generator 的底層實現(xiàn)機制是協(xié)程 Coroutine。 

  1. function* foo() {  
  2.     console.log("foo start")  
  3.     a = yield 1;  
  4.     console.log("foo a", a)  
  5.     yield 2;  
  6.     yield 3;  
  7.     console.log("foo end")  
  8.  
  9. const gen = foo();  
  10. console.log(gen.next().value); // 1  
  11. // gen.send("a") // http://www.voidcn.com/article/p-syzbwqht-bvv.html SpiderMonkey引擎支持 send 語法  
  12. console.log(gen.next().value); // 2  
  13. console.log(gen.next().value); // 3 
  14. console.log(foo().next().value); // 1  
  15. console.log(foo().next().value); // 1  
  16. /*  
  17. foo start  
  18.  
  19. foo a undefined  
  20.  
  21.  
  22. foo start  
  23.  
  24. foo start  
  25.  
  26. */ 

Python 協(xié)程成熟體

可等待對象可以在 await 語句中使用,可等待對象有三種主要類型:協(xié)程(coroutine), 任務(wù)(task) 和 Future。

協(xié)程(coroutine)

  •  協(xié)程函數(shù):定義形式為 async def 的函數(shù);
  •  協(xié)程對象:調(diào)用 協(xié)程函數(shù) 所返回的對象
  •  舊式基于 generator(生成器)的協(xié)程

任務(wù)(Task 對象):

  •  任務(wù) 被用來“并行的”調(diào)度協(xié)程, 當一個協(xié)程通過 asyncio.create_task() 等函數(shù)被封裝為一個 任務(wù),該協(xié)程會被自動調(diào)度執(zhí)行
  •  Task 對象被用來在事件循環(huán)中運行協(xié)程。如果一個協(xié)程在等待一個 Future 對象,Task 對象會掛起該協(xié)程的執(zhí)行并等待該 Future 對象完成。當該 Future 對象 完成,被打包的協(xié)程將恢復(fù)執(zhí)行。
  •  事件循環(huán)使用協(xié)同日程調(diào)度: 一個事件循環(huán)每次運行一個 Task 對象。而一個 Task 對象會等待一個 Future 對象完成,該事件循環(huán)會運行其他 Task、回調(diào)或執(zhí)行 IO 操作。
  •  asyncio.Task 從 Future 繼承了其除 Future.set_result() 和 Future.set_exception() 以外的所有 API。

未來對象(Future):

  •  Future 對象用來鏈接 底層回調(diào)式代碼 和高層異步/等待式代碼。
  •  不用回調(diào)方法編寫異步代碼后,為了獲取異步調(diào)用的結(jié)果,引入一個 Future 未來對象。Future 封裝了與 loop 的交互行為,add_done_callback 方法向 epoll 注冊回調(diào)函數(shù),當 result 屬性得到返回值后,會運行之前注冊的回調(diào)函數(shù),向上傳遞給 coroutine。

幾種事件循環(huán)(event loop):

  •  libevent/libev:Gevent(greenlet + 前期 libevent,后期 libev)使用的網(wǎng)絡(luò)庫,廣泛應(yīng)用;
  •  tornado:tornado 框架自己實現(xiàn)的 IOLOOP;
  •  picoev:meinheld(greenlet+picoev)使用的網(wǎng)絡(luò)庫,小巧輕量,相較于 libevent 在數(shù)據(jù)結(jié)構(gòu)和事件檢測模型上做了改進,所以速度更快。但從 github 看起來已經(jīng)年久失修,用的人不多。
  •  uvloop:Python3 時代的新起之秀。Guido 操刀打造了 asyncio 庫,asyncio 可以配置可插拔的event loop,但需要滿足相關(guān)的 API 要求,uvloop 繼承自 libuv,將一些低層的結(jié)構(gòu)體和函數(shù)用 Python 對象包裝。目前 Sanic 框架基于這個庫

例子 

  1. import asyncio  
  2. import time  
  3. async def exec():  
  4.     await asyncio.sleep(2)  
  5.     print('exec')  
  6. # 這種會和同步效果一直  
  7. # async def go():  
  8. #     print(time.time())  
  9. #     c1 = exec()  
  10. #     c2 = exec()  
  11. #     print(c1, c2)  
  12. #     await c1  
  13. #     await c2  
  14. #     print(time.time())  
  15. # 正確用法  
  16. async def go():  
  17.     print(time.time())  
  18.     await asyncio.gather(exec(),exec()) # 加入?yún)f(xié)程組統(tǒng)一調(diào)度 
  19.     print(time.time())  
  20. if __name__ == "__main__":  
  21.     asyncio.run(go()) 

JavaScript 協(xié)程成熟體

Promise 繼續(xù)使用

Promise 本質(zhì)是一個狀態(tài)機,用于表示一個異步操作的最終完成 (或失敗), 及其結(jié)果值。它有三個狀態(tài):

  •  pending: 初始狀態(tài),既不是成功,也不是失敗狀態(tài)。
  •  fulfilled: 意味著操作成功完成。
  •  rejected: 意味著操作失敗。

最終 Promise 會有兩種狀態(tài),一種成功,一種失敗,當 pending 變化的時候,Promise 對象會根據(jù)最終的狀態(tài)調(diào)用不同的處理函數(shù)。

async、await語法糖

async、await 是對 Generator 和 Promise 組合的封裝,使原先的異步代碼在形式上更接近同步代碼的寫法,并且對錯誤處理/條件分支/異常堆棧/調(diào)試等操作更友好。

js 異步執(zhí)行的運行機制

  1.  所有任務(wù)都在主線程上執(zhí)行,形成一個執(zhí)行棧。
  2.  主線程之外,還存在一個"任務(wù)隊列"(task queue)。只要異步任務(wù)有了運行結(jié)果,就在"任務(wù)隊列"之中放置一個事件。
  3.  一旦"執(zhí)行棧"中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會讀取"任務(wù)隊列"。那些對應(yīng)的異步任務(wù),結(jié)束等待狀態(tài),進入執(zhí)行棧并開始執(zhí)行。

遇到同步任務(wù)直接執(zhí)行,遇到異步任務(wù)分類為宏任務(wù)(macro-task)和微任務(wù)(micro-task)。

當前執(zhí)行棧執(zhí)行完畢時會立刻先處理所有微任務(wù)隊列中的事件,然后再去宏任務(wù)隊列中取出一個事件。同一次事件循環(huán)中,微任務(wù)永遠在宏任務(wù)之前執(zhí)行。

例子 

  1. var sleep = function (time) {  
  2.     console.log("sleep start")  
  3.     return new Promise(function (resolve, reject) {  
  4.         setTimeout(function () {  
  5.             resolve();  
  6.         }, time);  
  7.     });  
  8. };  
  9. async function exec() {  
  10.     await sleep(2000);  
  11.     console.log("sleep end")  
  12.  
  13. async function go() {  
  14.     console.log(Date.now())  
  15.     c1 = exec()  
  16.     console.log("-------1")  
  17.     c2 = exec()  
  18.     console.log(c1, c2)  
  19.     await c1;  
  20.     console.log("-------2")  
  21.     await c2;  
  22.     console.log(c1, c2)  
  23.     console.log(Date.now())  
  24. go();

event loop 將任務(wù)劃分:

  •  主線程循環(huán)從"任務(wù)隊列"中讀取事件
  •  宏隊列(macro task)js 同步執(zhí)行的代碼塊,setTimeout、setInterval、XMLHttprequest、setImmediate、I/O、UI rendering等,本質(zhì)是參與了事件循環(huán)的任務(wù)
  • 微隊列(micro task)Promise、process.nextTick(node環(huán)境)、Object.observe, MutationObserver等,本質(zhì)是直接在 Javascript 引擎中的執(zhí)行的沒有參與事件循環(huán)的任務(wù)

擴展閱讀 Node.js 中的 EventLoop (http://www.ruanyifeng.com/blog/2014/10/event-loop.html)

總結(jié)與對比

說明 python JavaScript 點評
進程 單進程 單進程 一致
中斷/恢復(fù) yield,yield from,next,send yield,next 基本相同,但 JavaScript 對 send 沒啥需求
未來對象(回調(diào)包裝) Futures Promise 解決 callback,思路相同
生成器 generator Generator 將 yield 封裝為協(xié)程Coroutine,思路一樣
成熟后關(guān)鍵詞 async、await async、await 關(guān)鍵詞支持,一毛一樣
事件循環(huán) asyncio 應(yīng)用的核心。事件循環(huán)會運行異步任務(wù)和回調(diào),執(zhí)行網(wǎng)絡(luò) IO 操作,以及運行子進程。asyncio 庫支持的 API 較多,可控性高 基于瀏覽器環(huán)境基本是黑盒,外部基本無法控制,對任務(wù)有做優(yōu)先級分類,調(diào)度方式有區(qū)別 這里有很大區(qū)別,運行環(huán)境不同,對任務(wù)的調(diào)度先后不同,Python 可能和 Node.js 關(guān)于事件循環(huán)的可比性更高些,這里還需需要繼續(xù)學(xué)習(xí)

到這里就基本結(jié)束了,看完不知道你會有什么感想,如有錯誤還請不吝賜教。 

 

責(zé)任編輯:龐桂玉 來源: 菜鳥學(xué)Python
相關(guān)推薦

2023-11-17 11:36:59

協(xié)程纖程操作系統(tǒng)

2025-06-26 04:10:00

2021-12-09 06:41:56

Python協(xié)程多并發(fā)

2024-02-05 09:06:25

Python協(xié)程Asyncio庫

2017-09-22 16:08:16

Python協(xié)程編程

2023-10-12 09:46:00

并發(fā)模型線程

2023-10-24 19:37:34

協(xié)程Java

2022-04-19 20:39:03

協(xié)程多進程

2025-02-08 09:13:40

2017-08-10 15:50:44

PHP協(xié)程阻塞

2024-06-27 07:56:49

2017-06-15 13:15:39

Python協(xié)程

2017-09-06 09:26:03

Python生成器協(xié)程

2021-04-25 09:36:20

Go協(xié)程線程

2022-09-06 20:30:48

協(xié)程Context主線程

2025-06-03 00:00:02

Go協(xié)程鎖機制

2016-10-28 17:39:47

phpgolangcoroutine

2017-05-02 11:38:00

PHP協(xié)程實現(xiàn)過程

2023-08-08 07:18:17

協(xié)程管道函數(shù)

2020-11-29 17:03:08

進程線程協(xié)程
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 亚洲精品乱码8久久久久久日本 | 欧美国产精品一区二区 | 亚洲精品自在在线观看 | 色综合天天天天做夜夜夜夜做 | 欧美久久一区 | 国产99久久精品一区二区永久免费 | 日本在线一区二区三区 | 亚洲成人黄色 | 日韩久久精品 | 欧美一级精品片在线看 | 日本精品视频在线观看 | 久久精品国产久精国产 | 国产精品毛片一区二区三区 | 欧美精品在线一区二区三区 | 午夜精品一区二区三区免费视频 | www.亚洲一区二区三区 | 极品国产视频 | 亚洲精品99 | 精品少妇一区二区三区日产乱码 | 欧美日韩中文国产一区发布 | 美女久久久| 精国产品一区二区三区四季综 | 欧美一级特黄aaa大片在线观看 | 国产精品免费观看视频 | 欧美日韩一区二区在线 | 欧美一区二区三区在线观看视频 | 欧美日韩精品免费观看 | 91久久国产综合久久91精品网站 | 国产偷录视频叫床高潮对白 | 欧美黄在线观看 | 国产露脸国语对白在线 | 国产成人在线观看免费 | 国产福利在线 | 午夜寂寞网站 | 日本精品视频 | 精品一区二区在线观看 | 一区二区三区免费 | 成人国产精品 | 人人澡视频 | 午夜精品一区二区三区在线视频 | 国产成人综合在线 |