溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

golang協(xié)程的實(shí)現(xiàn)方法

發(fā)布時(shí)間:2021-06-16 15:14:19 來(lái)源:億速云 閱讀:277 作者:chen 欄目:編程語(yǔ)言

這篇文章主要介紹“golang協(xié)程的實(shí)現(xiàn)方法”,在日常操作中,相信很多人在golang協(xié)程的實(shí)現(xiàn)方法問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”golang協(xié)程的實(shí)現(xiàn)方法”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

協(xié)程是應(yīng)用層的線程。

應(yīng)用層是相對(duì)于內(nèi)核層而言,是操作系統(tǒng)的概念,對(duì)應(yīng)的是cpu的運(yùn)行級(jí)別。操作系統(tǒng)的核心代碼運(yùn)行的ring0級(jí)別,應(yīng)用程序的代碼運(yùn)行在ring3級(jí)別。內(nèi)核與應(yīng)用層的級(jí)別設(shè)置保證了一些高權(quán)限的操作只有內(nèi)核代碼能做,應(yīng)用程序要使用這些功能必須通過(guò)調(diào)用操作系統(tǒng)的API(linux上稱為系統(tǒng)調(diào)用)來(lái)調(diào)用內(nèi)核的代碼。這個(gè)調(diào)用會(huì)導(dǎo)致cpu從ring3到ring0的上下文切換,這個(gè)切換是耗費(fèi)一些cpu時(shí)間的。

線程是操作系統(tǒng)的內(nèi)核對(duì)象,多線程編程時(shí),如果線程數(shù)過(guò)多,就會(huì)導(dǎo)致頻繁的上下文切換,這些cpu時(shí)間是一個(gè)額外的耗費(fèi)。所以在一些高并發(fā)的網(wǎng)絡(luò)服務(wù)器編程中,使用一個(gè)線程服務(wù)一個(gè)socket連接是很不明智的。于是操作系統(tǒng)提供了基于事件模式的異步編程模型。用少量的線程來(lái)服務(wù)大量的網(wǎng)絡(luò)連接和I/O操作。但是采用異步和基于事件的編程模型,復(fù)雜化了程序代碼的編寫(xiě),非常容易出錯(cuò)。因?yàn)榫€程穿插,也提高排查錯(cuò)誤的難度。

協(xié)程,是在應(yīng)用層模擬的線程,他避免了上下文切換的額外耗費(fèi),兼顧了多線程的優(yōu)點(diǎn)。簡(jiǎn)化了高并發(fā)程序的復(fù)雜度。舉個(gè)例子,一個(gè)高并發(fā)的網(wǎng)絡(luò)服務(wù)器,每一個(gè)socket連接進(jìn)來(lái),服務(wù)器用一個(gè)協(xié)程來(lái)對(duì)他進(jìn)行服務(wù)。代碼非常清晰。而且兼顧了性能。

那么,協(xié)程是怎么實(shí)現(xiàn)的呢?

他和線程的原理是一樣的,當(dāng)a線程切換到b線程的時(shí)候,需要將a線程的相關(guān)執(zhí)行進(jìn)度壓入棧,然后將b線程的執(zhí)行進(jìn)度出棧,進(jìn)入b的執(zhí)行序列。協(xié)程只不過(guò)是在應(yīng)用成實(shí)現(xiàn)這一點(diǎn)。

但是,協(xié)程并不是有操作系統(tǒng)調(diào)度的,而且應(yīng)用程序也沒(méi)有能力和權(quán)限執(zhí)行cpu調(diào)度。怎么解決這個(gè)問(wèn)題?

答案是,協(xié)程是基于線程的。內(nèi)部實(shí)現(xiàn)上,維護(hù)了一組數(shù)據(jù)結(jié)構(gòu)和n個(gè)線程,真正的執(zhí)行還是線程,協(xié)程執(zhí)行的代碼被扔進(jìn)一個(gè)待執(zhí)行隊(duì)列中,有這n個(gè)線程從隊(duì)列中拉出來(lái)執(zhí)行。這就解決了協(xié)程的執(zhí)行問(wèn)題。那么協(xié)程是怎么切換的呢?答案是:golang對(duì)各種io函數(shù)進(jìn)行了封裝,這些封裝的函數(shù)提供給應(yīng)用程序使用,而其內(nèi)部調(diào)用了操作系統(tǒng)的異步io函數(shù),當(dāng)這些異步函數(shù)返回busy或bloking時(shí),golang利用這個(gè)時(shí)機(jī)將現(xiàn)有的執(zhí)行序列壓棧,讓線程去拉另外一個(gè)協(xié)程的代碼來(lái)執(zhí)行,基本原理就是這樣,利用并封裝了操作系統(tǒng)的異步函數(shù)。包括linux的epoll,select和windows的iocp,event等。

由于golang是從編譯器和語(yǔ)言基礎(chǔ)庫(kù)多個(gè)層面對(duì)協(xié)程做了實(shí)現(xiàn),所以,golang的協(xié)程是目前各類有協(xié)程概念的語(yǔ)言中實(shí)現(xiàn)的最完整和成熟的。

十萬(wàn)個(gè)協(xié)程同時(shí)運(yùn)行也毫無(wú)壓力。關(guān)鍵我們不會(huì)這么寫(xiě)代碼。但是總體而言,程序員可以在編寫(xiě)golang的代碼是,可以更多的關(guān)注業(yè)務(wù)邏輯的實(shí)現(xiàn),更少的在這些關(guān)鍵的基礎(chǔ)構(gòu)件上耗費(fèi)太多精力。

到此,關(guān)于“golang協(xié)程的實(shí)現(xiàn)方法”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI