日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php開(kāi)源 > php教程 > golang技術(shù)隨筆(二)理解goroutine

golang技術(shù)隨筆(二)理解goroutine

來(lái)源:程序員人生   發(fā)布時(shí)間:2015-03-31 08:09:47 閱讀次數(shù):4721次

進(jìn)程、線程和協(xié)程

要理解甚么是goroutine,我們先來(lái)看看進(jìn)程、線程和協(xié)程它們之間的區(qū)分,這能幫助我們更好的理解goroutine。

進(jìn)程:分配完全獨(dú)立的地址空間,具有自己獨(dú)立的堆和棧,既不同享堆,亦不同享?xiàng)#M(jìn)程的切換只產(chǎn)生在內(nèi)核態(tài),由操作系統(tǒng)調(diào)度。
線程:和其它本進(jìn)程的線程同享地址空間,具有自己獨(dú)立的棧和同享的堆,同享堆,不同享?xiàng)#€程的切換1般也由操作系統(tǒng)調(diào)度(標(biāo)準(zhǔn)線程是的)。
協(xié)程:和線程類似,同享堆,不同享?xiàng)#瑓f(xié)程的切換1般由程序員在代碼中顯式控制。

進(jìn)程和線程的切換主要依賴于時(shí)間片的控制(關(guān)于進(jìn)程和線程的調(diào)度方式,具體可參看這篇文章:http://blog.chinaunix.net/uid⑵0476365-id⑴942505.html),而協(xié)程的切換則主要依賴于本身,這樣的好處是避免了無(wú)意義的調(diào)度,由此可以提高性能,但也因此,程序員必須自己承當(dāng)調(diào)度的責(zé)任。

goroutine可以看做是協(xié)程的go語(yǔ)言實(shí)現(xiàn),從百度百科上看協(xié)程的定義:與子例程1樣,協(xié)程(coroutine)也是1種程序組件。相對(duì)子例程而言,協(xié)程更加1般和靈活,但在實(shí)踐中使用沒(méi)有子例程那樣廣泛。實(shí)際上,我們可以把子例程當(dāng)作是協(xié)程的1種特例。1般來(lái)講,如果沒(méi)有顯式的讓出CPU,就會(huì)1直履行當(dāng)前協(xié)程。

淺析goroutine

我們知道goroutine是協(xié)程的go語(yǔ)言實(shí)現(xiàn),它是語(yǔ)言原生支持的,相對(duì)1般由庫(kù)實(shí)現(xiàn)協(xié)程的方式,goroutine更加強(qiáng)大,它的調(diào)度1定程度上是由go運(yùn)行時(shí)(runtime)管理。其好處之1是,當(dāng)某goroutine產(chǎn)生阻塞時(shí)(例猶如步IO操作等),會(huì)自動(dòng)出讓CPU給其它goroutine。

goroutine的使用非常簡(jiǎn)單,例如foo是1個(gè)函數(shù):

go foo()

就1個(gè)關(guān)鍵字go弄定了,這里會(huì)啟動(dòng)1個(gè)goroutine履行foo函數(shù),然后CPU繼續(xù)履行后面的代碼。這里雖然啟動(dòng)了goroutine,但其實(shí)不意味著它會(huì)得到馬上調(diào)度,關(guān)于goroutine的調(diào)度我們稍后再探討。

goroutine是非常輕量級(jí)的,它就是1段代碼,1個(gè)函數(shù)入口,和在堆上為其分配的1個(gè)堆棧(初始大小為4K,會(huì)隨著程序的履行自動(dòng)增長(zhǎng)刪除)。所以它非常便宜,我們可以很輕松的創(chuàng)建上萬(wàn)個(gè)goroutine。

go運(yùn)行時(shí)調(diào)度

默許的, 所有g(shù)oroutine會(huì)在1個(gè)原生線程里跑,也就是只使用了1個(gè)CPU核。在同1個(gè)原生線程里,如果當(dāng)前goroutine不產(chǎn)生阻塞,它是不會(huì)讓出CPU時(shí)間給其他同線程的goroutines的。除被系統(tǒng)調(diào)用阻塞的線程外,Go運(yùn)行庫(kù)最多會(huì)啟動(dòng)$GOMAXPROCS個(gè)線程來(lái)運(yùn)行g(shù)oroutine。

那末goroutine究竟是如何被調(diào)度的呢?我們從go程序啟動(dòng)開(kāi)始說(shuō)起。在go程序啟動(dòng)時(shí)會(huì)首先創(chuàng)建1個(gè)特殊的內(nèi)核線程sysmon,從名字就能夠看出來(lái)它的職責(zé)是負(fù)責(zé)監(jiān)控的,goroutine背后的調(diào)度可以說(shuō)就是靠它來(lái)弄定。

接下來(lái),我們?cè)倏纯此恼{(diào)度模型,go語(yǔ)言當(dāng)前的實(shí)現(xiàn)是N:M。即1定數(shù)量的用戶線程映照到1定數(shù)量的OS線程上,這里的用戶線程在go中指的就是goroutine。go語(yǔ)言的調(diào)度模型需要弄清楚3個(gè)概念:M、P和G,以下圖表示:
這里寫(xiě)圖片描述
M代表OS線程,G代表goroutine,P的概念比較重要,它表示履行的上下文,其數(shù)量由$GOMAXPROCS決定,1般來(lái)講正好等于處理器的數(shù)量。M必須和P綁定才能履行G,調(diào)度器需要保證所有的P都有G履行,以保證并行度。以下圖:
這里寫(xiě)圖片描述
從圖中我們可以看見(jiàn),當(dāng)前有兩個(gè)P,各自綁定了1個(gè)M,并分別履行了1個(gè)goroutine,我們還可以看見(jiàn)每一個(gè)P上還掛了1個(gè)G的隊(duì)列,這個(gè)隊(duì)列是代表私有的任務(wù)隊(duì)列,它們實(shí)際上都是runnable狀態(tài)的goroutine。當(dāng)使用go關(guān)鍵字聲明時(shí),1個(gè)goroutine便被加入到運(yùn)行隊(duì)列的尾部。1旦1個(gè)goroutine運(yùn)行到1個(gè)調(diào)度點(diǎn),上下文便從運(yùn)行隊(duì)列中取出1個(gè)goroutine, 設(shè)置好棧和指令指針,便開(kāi)始運(yùn)行新的goroutine。

那末go中切換goroutine的調(diào)度點(diǎn)有哪些呢?具體有以下3種情況

  • 調(diào)用runtime?gosched函數(shù)。goroutine主動(dòng)放棄CPU,該goroutine會(huì)被設(shè)置為runnable狀態(tài),然后放入1個(gè)全局等待隊(duì)列中,而P將繼續(xù)履行下1個(gè)goroutine。使用runtime?gosched函數(shù)是1個(gè)主動(dòng)的行動(dòng),1般是在履行長(zhǎng)任務(wù)時(shí)又想其它goroutine得到履行的機(jī)會(huì)時(shí)調(diào)用。
  • 調(diào)用runtime?park函數(shù)。goroutine進(jìn)入waitting狀態(tài),除非對(duì)其調(diào)用runtime?ready函數(shù),否則該goroutine將永久不會(huì)得到履行。而P將繼續(xù)履行下1個(gè)goroutine。使用runtime?park函數(shù)1般是在某個(gè)條件如果得不到滿足就不能繼續(xù)運(yùn)行下去時(shí)調(diào)用,當(dāng)條件滿足后需要使用runtime?ready以喚醒它(這里喚醒以后是不是會(huì)加入全局等待隊(duì)列還有待研究)。像channel操作,定時(shí)器中,網(wǎng)絡(luò)poll等都有可能park goroutine。
  • 慢系統(tǒng)調(diào)用。這樣的系統(tǒng)調(diào)用會(huì)阻塞等待,為了使該P(yáng)上掛著的其它G也能得到履行的機(jī)會(huì),需要將這些goroutine轉(zhuǎn)到另外一個(gè)OS線程上去。具體的做法是:首先將該P(yáng)設(shè)置為syscall狀態(tài),然后該線程進(jìn)入系統(tǒng)調(diào)用阻塞等待。之條件到過(guò)的sysmom線程會(huì)定期掃描所有的P,發(fā)現(xiàn)1個(gè)P處于了syscall的狀態(tài),就將M和P分離(實(shí)際上只有當(dāng) Syscall 履行時(shí)間超越某個(gè)閾值時(shí),才會(huì)將 M 與 P 分離)。RUNTIME會(huì)再分配1個(gè)M和這個(gè)P綁定,從而繼續(xù)履行隊(duì)列中的其它G。而當(dāng)之前阻塞的M從系統(tǒng)調(diào)用中返回后,會(huì)將該goroutine放入全局等待隊(duì)列中,自己則sleep去。
    這里寫(xiě)圖片描述
    該圖描寫(xiě)了M和P的分離進(jìn)程。

調(diào)度點(diǎn)的情況說(shuō)清楚了,但全部模型還其實(shí)不完全。我們知道當(dāng)使用go去調(diào)用1個(gè)函數(shù),會(huì)生成1個(gè)新的goroutine放入當(dāng)前P的隊(duì)列中,那末甚么時(shí)候生成別的OS線程,各個(gè)OS線程又是如何做負(fù)載均衡的呢?

當(dāng)M從隊(duì)列中拿到1個(gè)可履行的G后,首先會(huì)去檢查1下,自己的隊(duì)列中是不是還有等待的G,如果還有等待的G,并且也還有空閑的P,此時(shí)就會(huì)通知runtime分配1個(gè)新的M(如果有在睡覺(jué)的OS線程,則直接喚醒它,沒(méi)有的話則生成1個(gè)新的OS線程)來(lái)分擔(dān)負(fù)務(wù)。

如果某個(gè)M發(fā)現(xiàn)隊(duì)列為空以后,會(huì)首先從全局隊(duì)列中取1個(gè)G來(lái)處理。如果全局隊(duì)列也空了,則會(huì)隨機(jī)從別的P那里直接截取1半的隊(duì)列過(guò)來(lái)(偷竊任務(wù)),如果發(fā)現(xiàn)所有的P都沒(méi)有可供偷竊的G了,該M就會(huì)墮入沉睡。

全部調(diào)度模型大致就是這模樣了,和所有協(xié)程的調(diào)度1樣,在響應(yīng)時(shí)間上,這類協(xié)作式調(diào)度是硬傷。很容易致使某個(gè)協(xié)程長(zhǎng)時(shí)間沒(méi)法得到履行。但整體來(lái)講,它帶來(lái)的好處更加讓人驚嘆。想要了解的更多可以看看我下面列出的1些參考資料,或是直接看它的源碼:http://golang.org/src/runtime/proc.c

總綱傳送門(mén):golang技術(shù)隨筆總綱

參考資料

  1. 協(xié)程
  2. goroutine背后的系統(tǒng)知識(shí)
  3. The Go scheduler
  4. goroutine與調(diào)度器
生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 欧美日韩免费一区二区三区 | 国产高清一区 | 91综合在线 | 国产精品视频一二三区 | 黄色一级毛片 | 亚洲一区国产精品 | 国产剧情一区二区三区 | 91久久精品一区二区别 | aⅴ一级片 | 老牛影视免费一区二区 | 亚洲尤物 | 国产一区二区精品 | 欧美一区二区不卡视频 | 亚洲免费av片| 国产精品综合 | 欧美激情视频在线播放 | 精品美女久久久 | xxxx性欧美 | 99视频这里有精品 | 国产电影av| 欧美特级一级片 | 亚洲国产不卡 | 在线黄色av网站 | 欧美日韩亚洲在线 | 国产精品久久9 | 国产精品1区 | 国产小视频在线播放 | 91亚洲成人 | 精品一区二区三区在线播放 | 成人欧美一区二区三区黑人孕妇 | 亚洲黄色一区二区三区 | 国产精品麻豆入口29 | 国产免费不卡 | 欧美性一区| 日产精品久久久 | 欧美成人精品一区二区三区在线看 | 18视频网站在线观看 | 日本欧美国产 | 一区二区网站 | 日韩精品影片 | 欧美三级免费网站 |