摘要:它避免了上下文切換的額外耗費(fèi),兼顧了多線程的優(yōu)點(diǎn),簡化了高并發(fā)程序的復(fù)雜。而可以理解為一種語言的協(xié)程。線程輕量級進(jìn)程,,是程序執(zhí)行流的最小單元。一個(gè)標(biāo)準(zhǔn)的線程由線程,當(dāng)前指令指針,寄存器集合和堆棧組成。其實(shí)就是或者等語言中的多線程開發(fā)。
grape
全部視頻:https://segmentfault.com/a/11...
原視頻地址:https://biglive.xueersi.com/L...
GO協(xié)程有關(guān)知識(擴(kuò)展)Go語言最大的特色就是從語言層面支持并發(fā)(Goroutine),Goroutine是Go中最基本的執(zhí)行單元。事實(shí)上每一個(gè)Go程序至少有一個(gè)Goroutine:主Goroutine。當(dāng)程序啟動時(shí),它會自動創(chuàng)建。
首先了解什么是協(xié)程,什么是線程
協(xié)程:又稱微線程與子例程(或者稱為函數(shù))一樣,協(xié)程(coroutine)也是一種程序組件。相對子例程而言,協(xié)程更為一般和靈活,但在實(shí)踐中使用沒有子例程那樣廣泛。和線程類似,共享堆,不共享?xiàng)?,協(xié)程的切換一般由程序員在代碼中顯式控制。它避免了上下文切換的額外耗費(fèi),兼顧了多線程的優(yōu)點(diǎn),簡化了高并發(fā)程序的復(fù)雜。而Goroutine可以理解為一種Go語言的協(xié)程。同時(shí)它可以運(yùn)行在一個(gè)或多個(gè)線程上。
線程:輕量級進(jìn)程(Lightweight Process,LWP),是程序執(zhí)行流的最小單元。一個(gè)標(biāo)準(zhǔn)的線程由線程ID,當(dāng)前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進(jìn)程中的一個(gè)實(shí)體,是被系統(tǒng)獨(dú)立調(diào)度和分派的基本單位,線程自己不擁有系統(tǒng)資源,只擁有一點(diǎn)兒在運(yùn)行中必不可少的資源,但它可與同屬一個(gè)進(jìn)程的其它線程共享進(jìn)程所擁有的全部資源。線程擁有自己獨(dú)立的棧和共享的堆,共享堆,不共享?xiàng)?,線程的切換一般也由操作系統(tǒng)調(diào)度。
區(qū)別:協(xié)程是運(yùn)行在線程上的,在代碼中顯示控制,沒有上下文切換所消耗的資源,協(xié)程擁有??臻g來存儲自己的上下文,如果??臻g不足,則會更改其他的協(xié)程。
Go實(shí)現(xiàn)了兩種并發(fā)形式。第一種是大家普遍認(rèn)知的:多線程共享內(nèi)存。其實(shí)就是Java或者C++等語言中的多線程開發(fā)。另外一種是Go語言特有的,也是Go語言推薦的:CSP(communicating sequential processes)并發(fā)模型。
CSP并發(fā)模型:以通信的方式來共享內(nèi)存,傳統(tǒng)的多線程之間以共享內(nèi)存來進(jìn)行通信,GO語言則以通信的方式來共享內(nèi)存,那么就來說一說這個(gè)CSP模型,它是通過goroutine和channel來實(shí)現(xiàn)的。
- goroutine 是Go語言中并發(fā)的執(zhí)行單位。有點(diǎn)抽象,其實(shí)就是和傳統(tǒng)概念上的”線程“類似,可以理解為”線程“。 - channel是Go語言中各個(gè)并發(fā)結(jié)構(gòu)體(goroutine)之前的通信機(jī)制。 通俗的講,就是各個(gè)goroutine之間通信的”管道“,有點(diǎn)類似于Linux中的管道。
生成一個(gè)goroutine需要代碼簡簡單單的go func()就可以生成,channel也是需要聲明chan即可,同時(shí),channel在使用時(shí)需要注意,在讀和寫的時(shí)候channel都是堵塞的,向管道里寫或者讀數(shù)據(jù)類似于流輸入輸出。
GO并發(fā)的實(shí)現(xiàn)原理我們先從線程講起,無論語言層面何種并發(fā)模型,到了操作系統(tǒng)層面,一定是以線程的形態(tài)存在的。而操作系統(tǒng)根據(jù)資源訪問權(quán)限的不同,體系架構(gòu)可分為用戶空間和內(nèi)核空間;內(nèi)核空間主要操作訪問CPU資源、I/O資源、內(nèi)存資源等硬件資源,為上層應(yīng)用程序提供最基本的基礎(chǔ)資源,用戶空間呢就是上層應(yīng)用程序的固定活動空間,用戶空間不可以直接訪問資源,必須通過“系統(tǒng)調(diào)用”、“庫函數(shù)”或“Shell腳本”來調(diào)用內(nèi)核空間提供的資源。
我們現(xiàn)在的計(jì)算機(jī)語言,可以狹義的認(rèn)為是一種“軟件”,它們中所謂的“線程”,往往是用戶態(tài)的線程,和操作系統(tǒng)本身內(nèi)核態(tài)的線程(簡稱KSE),還是有區(qū)別的。也就是說無論你怎么去實(shí)現(xiàn)并發(fā),其實(shí)根本上都是去調(diào)用內(nèi)核態(tài)的線程,一切并發(fā)都是紙老虎~
線程模型的實(shí)現(xiàn),可以分為以下幾種方式:1.用戶級線程模型,2.內(nèi)核級線程模型,3.兩級線程模型。而我們的GO線程模型就是一種特殊的兩級線程模型(GPM調(diào)度模型)。
GPM調(diào)度模型:G: 表示goroutine,存儲了goroutine的執(zhí)行stack信息、goroutine狀態(tài)以及goroutine的任務(wù)函數(shù)等;
P: 表示邏輯processor,P的數(shù)量決定了系統(tǒng)內(nèi)最大可并行的G的數(shù)量(前提:系統(tǒng)的物理cpu核數(shù)>=P的數(shù)量);P的最大作用還是其擁有的各種G對象隊(duì)列、鏈表、一些cache和狀態(tài)。
M: M代表著真正的執(zhí)行計(jì)算資源。在綁定有效的p后,進(jìn)入schedule循環(huán);而schedule循環(huán)的機(jī)制大致是從各種隊(duì)列、p的本地隊(duì)列中獲取G,切換到G的執(zhí)行棧上并執(zhí)行G的函數(shù),調(diào)用goexit做清理工作并回到m,如此反復(fù)。M并不保留G狀態(tài),這是G可以跨M調(diào)度的基礎(chǔ)。
P是一個(gè)“邏輯Proccessor”,每個(gè)G要想真正運(yùn)行起來,首先需要被分配一個(gè)P(進(jìn)入到P的local runq中,這里暫忽略global runq那個(gè)環(huán)節(jié))。對于G來說,P就是運(yùn)行它的“CPU”,可以說:G的眼里只有P。但從Go scheduler視角來看,真正的“CPU”是M,只有將P和M綁定才能讓P的runq中G得以真實(shí)運(yùn)行起來。
G-P-M模型的實(shí)現(xiàn)算是Go scheduler的一大進(jìn)步,但Scheduler仍然有一個(gè)頭疼的問題,那就是不支持搶占式調(diào)度,導(dǎo)致一旦某個(gè)G中出現(xiàn)死循環(huán)或永久循環(huán)的代碼邏輯,那么G將永久占用分配給它的P和M,位于同一個(gè)P中的其他G將得不到調(diào)度,出現(xiàn)“餓死”的情況。更為嚴(yán)重的是,當(dāng)只有一個(gè)P時(shí)(GOMAXPROCS=1)時(shí),整個(gè)Go程序中的其他G都將“餓死”。那怎么辦呢?在GO1.2中,他增加了一個(gè)監(jiān)控,Go程序啟動時(shí),runtime會去啟動一個(gè)名為sysmon的m(一般稱為監(jiān)控線程),該m無需綁定p即可運(yùn)行,該m在整個(gè)Go程序的運(yùn)行過程中至關(guān)重要:向長時(shí)間運(yùn)行的G任務(wù)發(fā)出搶占調(diào)度,收回因syscall長時(shí)間阻塞的P等等
如果G被阻塞在某個(gè)system call操作上,那么不光G會阻塞,執(zhí)行該G的M也會解綁P(實(shí)質(zhì)是被sysmon搶走了),與G一起進(jìn)入sleep狀態(tài)。如果此時(shí)有idle的M,則P與其綁定繼續(xù)執(zhí)行其他G;如果沒有idle M,但仍然有其他G要去執(zhí)行,那么就會創(chuàng)建一個(gè)新M。
參考文章:https://segmentfault.com/a/11...
https://blog.csdn.net/weixin_...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/31428.html
摘要:原文鏈接原文作者今天譯者注年月日是版本的發(fā)布日,同時(shí)會對協(xié)程的結(jié)構(gòu)化并發(fā)做一些介紹。進(jìn)一步的閱讀結(jié)構(gòu)化并發(fā)的概念背后有更多的哲學(xué)。現(xiàn)代語言開始為我們提供一種以完全非結(jié)構(gòu)化啟動并發(fā)任務(wù)的方式,這玩意該結(jié)束了。 原文鏈接:Structured concurrency 原文作者:Roman Elizarov 今天(譯者注:18年9月12日) 是 kotlinx.coroutines 0.26...
摘要:開發(fā)負(fù)責(zé)人創(chuàng)建分支,編寫單元測試腳本,編寫代碼,實(shí)現(xiàn)提案中的所有內(nèi)容,最終發(fā)起交叉評審,檢查代碼,提出改進(jìn)意見,反饋給開發(fā)負(fù)責(zé)人,繼續(xù)完善細(xì)節(jié)。 Swoole開源項(xiàng)目從2012年開始發(fā)布第一個(gè)版本,到現(xiàn)在已經(jīng)有近7年的歷史。在這七年的時(shí)間里: 提交了8821次代碼變更 發(fā)布了287個(gè)版本 收到并解決1161次issue反饋 合并了603次pull request 共有100位開發(fā)者...
摘要:為語言提供了強(qiáng)大的協(xié)程編程模式。提供的協(xié)程語法借鑒自,在此向開發(fā)組致敬協(xié)程可以與很好地互補(bǔ)。并發(fā)執(zhí)行使用創(chuàng)建協(xié)程,可以讓和兩個(gè)函數(shù)變成并發(fā)執(zhí)行。協(xié)程需要拿到請求的結(jié)果。 Swoole4為PHP語言提供了強(qiáng)大的CSP協(xié)程編程模式。底層提供了3個(gè)關(guān)鍵詞,可以方便地實(shí)現(xiàn)各類功能。 Swoole4提供的PHP協(xié)程語法借鑒自Golang,在此向GO開發(fā)組致敬 PHP+Swoole協(xié)程可以與...
摘要:關(guān)鍵字表示代碼在該處將會被阻塞式暫停阻塞的僅僅是函數(shù)代碼本身,而不是整個(gè)程序,但是這并沒有引起函數(shù)內(nèi)部自頂向下代碼的絲毫改變。通過實(shí)現(xiàn)模式在通過實(shí)現(xiàn)理論的過程中已經(jīng)有一些有趣的探索了。 至此本系列的四篇文章翻譯完結(jié),查看完整系列請移步blogs 由于個(gè)人能力知識有限,翻譯過程中難免有紕漏和錯誤,望不吝指正issue ES6 Generators: 完整系列 The Basics...
摘要:本周提交的一份增強(qiáng)建議草案要求將虛擬線程作為標(biāo)準(zhǔn)版的一部分進(jìn)行預(yù)覽。虛擬線程目的是更好地支持編寫和維護(hù)高吞吐量并發(fā)應(yīng)用程序。該提案指出,使用虛擬線程不需要學(xué)習(xí)新的編程模型。我們知道 Go 語言最大亮點(diǎn)之一就是原生支持并發(fā),這得益于 Go 語言的協(xié)程機(jī)制。一個(gè) go 語句就可以發(fā)起一個(gè)協(xié)程 (goroutin)。 協(xié)程本質(zhì)上是一種用戶態(tài)線程,它不需要操作系統(tǒng)來進(jìn)行調(diào)度,而是由用戶程序自行管理...
閱讀 3143·2021-11-11 16:54
閱讀 2319·2021-09-04 16:48
閱讀 3227·2019-08-29 16:08
閱讀 648·2019-08-29 15:13
閱讀 1353·2019-08-29 15:09
閱讀 2670·2019-08-29 12:45
閱讀 1934·2019-08-29 12:12
閱讀 458·2019-08-26 18:27