福哥答案2020-08-20:
創(chuàng)新互聯(lián)建站是由多位在大型網(wǎng)絡(luò)公司、廣告設(shè)計公司的優(yōu)秀設(shè)計人員和策劃人員組成的一個具有豐富經(jīng)驗的團隊,其中包括網(wǎng)站策劃、網(wǎng)頁美工、網(wǎng)站程序員、網(wǎng)頁設(shè)計師、平面廣告設(shè)計師、網(wǎng)絡(luò)營銷人員及形象策劃。承接:做網(wǎng)站、網(wǎng)站制作、網(wǎng)站改版、網(wǎng)頁設(shè)計制作、網(wǎng)站建設(shè)與維護、網(wǎng)絡(luò)推廣、數(shù)據(jù)庫開發(fā),以高性價比制作企業(yè)網(wǎng)站、行業(yè)門戶平臺等全方位的服務(wù)。
1.golang的協(xié)程是基于gpm機制,是可以多核多線程的。Python的協(xié)程是eventloop模型(IO多路復(fù)用技術(shù))實現(xiàn),協(xié)程是嚴格的 1:N 關(guān)系,也就是一個線程對應(yīng)了多個協(xié)程。雖然可以實現(xiàn)異步I/O,但是不能有效利用多核(GIL)。
2.golang用go func。python用import asyncio,async/await表達式。
評論
協(xié)程,又稱微線程,纖程。英文名 Coroutine 。Python對協(xié)程的支持是通過 generator 實現(xiàn)的。在generator中,我們不但可以通過for循環(huán)來迭代,還可以不斷調(diào)用 next()函數(shù) 獲取由 yield 語句返回的下一個值。但是Python的yield不但可以返回一個值,它還可以接收調(diào)用者發(fā)出的參數(shù)。yield其實是終端當前的函數(shù),返回給調(diào)用方。python3中使用yield來實現(xiàn)range,節(jié)省內(nèi)存,提高性能,懶加載的模式。
asyncio是Python 3.4 版本引入的 標準庫 ,直接內(nèi)置了對異步IO的支持。
從Python 3.5 開始引入了新的語法 async 和 await ,用來簡化yield的語法:
import asyncio
import threading
async def compute(x, y):
print("Compute %s + %s ..." % (x, y))
print(threading.current_thread().name)
await asyncio.sleep(x + y)
return x + y
async def print_sum(x, y):
result = await compute(x, y)
print("%s + %s = %s" % (x, y, result))
print(threading.current_thread().name)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
tasks = [print_sum(1, 2), print_sum(3, 4)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
線程是內(nèi)核進行搶占式的調(diào)度的,這樣就確保了每個線程都有執(zhí)行的機會。而 coroutine 運行在同一個線程中,由語言的運行時中的 EventLoop(事件循環(huán)) 來進行調(diào)度。和大多數(shù)語言一樣,在 Python 中,協(xié)程的調(diào)度是非搶占式的,也就是說一個協(xié)程必須主動讓出執(zhí)行機會,其他協(xié)程才有機會運行。
讓出執(zhí)行的關(guān)鍵字就是 await。也就是說一個協(xié)程如果阻塞了,持續(xù)不讓出 CPU,那么整個線程就卡住了,沒有任何并發(fā)。
PS: 作為服務(wù)端,event loop最核心的就是IO多路復(fù)用技術(shù),所有來自客戶端的請求都由IO多路復(fù)用函數(shù)來處理;作為客戶端,event loop的核心在于利用Future對象延遲執(zhí)行,并使用send函數(shù)激發(fā)協(xié)程,掛起,等待服務(wù)端處理完成返回后再調(diào)用CallBack函數(shù)繼續(xù)下面的流程
Go語言的協(xié)程是 語言本身特性 ,erlang和golang都是采用了CSP(Communicating Sequential Processes)模式(Python中的協(xié)程是eventloop模型),但是erlang是基于進程的消息通信,go是基于goroutine和channel的通信。
Python和Go都引入了消息調(diào)度系統(tǒng)模型,來避免鎖的影響和進程/線程開銷大的問題。
協(xié)程從本質(zhì)上來說是一種用戶態(tài)的線程,不需要系統(tǒng)來執(zhí)行搶占式調(diào)度,而是在語言層面實現(xiàn)線程的調(diào)度 。因為協(xié)程 不再使用共享內(nèi)存/數(shù)據(jù) ,而是使用 通信 來共享內(nèi)存/鎖,因為在一個超級大系統(tǒng)里具有無數(shù)的鎖,共享變量等等會使得整個系統(tǒng)變得無比的臃腫,而通過消息機制來交流,可以使得每個并發(fā)的單元都成為一個獨立的個體,擁有自己的變量,單元之間變量并不共享,對于單元的輸入輸出只有消息。開發(fā)者只需要關(guān)心在一個并發(fā)單元的輸入與輸出的影響,而不需要再考慮類似于修改共享內(nèi)存/數(shù)據(jù)對其它程序的影響。
線程:
多線程是為了解決CPU利用率的問題,線程則是為了減少上下文切換時的開銷,進程和線程在Linux中沒有本質(zhì)區(qū)別,最大的不同就是進程有自己獨立的內(nèi)存空間,而線程是共享內(nèi)存空間。
在進程切換時需要轉(zhuǎn)換內(nèi)存地址空間,而線程切換沒有這個動作,所以線程切換比進程切換代價要小得多。
協(xié)程:
想要簡單,又要性能高,協(xié)程就可以達到我們的目的,它是用戶視角的一種抽象,操作系統(tǒng)并沒有這個概念,主要思想是在用戶態(tài)實現(xiàn)調(diào)度算法,用少量線程完成大量任務(wù)的調(diào)度。
Goroutine是GO語言實現(xiàn)的協(xié)程,其特點是在語言層面就支持,使用起來十分方便,它的核心是MPG調(diào)度模型:M即內(nèi)核線程;P即處理器,用來執(zhí)行Goroutine,它維護了本地可運行隊列;G即Goroutine,代碼和數(shù)據(jù)結(jié)構(gòu);S及調(diào)度器,維護M和P的信息。