您好,登錄后才能下訂單哦!
這篇文章主要介紹golang中線程和協(xié)程有哪些區(qū)別,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
區(qū)別:線程中數(shù)據(jù)存儲(chǔ)在內(nèi)核態(tài)的內(nèi)存空間;而協(xié)程中數(shù)據(jù)存儲(chǔ)在線程提供的用戶態(tài)內(nèi)存空間。線程的任務(wù)調(diào)度由內(nèi)核實(shí)現(xiàn),搶占方式,依賴各種鎖;協(xié)程的任務(wù)調(diào)度由用戶態(tài)實(shí)現(xiàn)的具體調(diào)度器進(jìn)行。
協(xié)程
協(xié)程,英文名Coroutine。但在 Go 語言中,協(xié)程的英文名是:gorutine。它常常被用于進(jìn)行多任務(wù),即并發(fā)作業(yè)。沒錯(cuò),就是多線程作業(yè)的那個(gè)作業(yè)。
雖然在 Go 中,我們不用直接編寫線程之類的代碼來進(jìn)行并發(fā),但是 Go 的協(xié)程卻依賴于線程來進(jìn)行。
下面我們來看看它們的區(qū)別。
線程的基礎(chǔ)介紹,這里請自行網(wǎng)上搜索文章,因?yàn)殛P(guān)于線程的優(yōu)秀介紹文章已經(jīng)很多。
協(xié)程的特點(diǎn)
這里先直接列出線程的特點(diǎn),然后從例子中進(jìn)行解析。
多個(gè)協(xié)程可由一個(gè)或多個(gè)線程管理,協(xié)程的調(diào)度發(fā)生在其所在的線程中。
可以被調(diào)度,調(diào)度策略由應(yīng)用層代碼定義,即可被高度自定義實(shí)現(xiàn)。
執(zhí)行效率高。
占用內(nèi)存少。
上面第 1和第 2點(diǎn)
我們來看一個(gè)例子: func TestGorutine(t *testing.T) { runtime.GOMAXPROCS(1) // 指定最大 P 為 1,從而管理協(xié)程最多的線程為 1 個(gè) wg := sync.WaitGroup{} // 控制等待所有協(xié)程都執(zhí)行完再退出程序 wg.Add(2) // 運(yùn)行一個(gè)協(xié)程 go func() { fmt.Println(1) fmt.Println(2) fmt.Println(3) wg.Done() }() // 運(yùn)行第二個(gè)協(xié)程 go func() { fmt.Println(65) fmt.Println(66) // 設(shè)置個(gè)睡眠,讓該協(xié)程執(zhí)行超時(shí)而被掛起,引起超時(shí)調(diào)度 time.Sleep(time.Second) fmt.Println(67) wg.Done() }() wg.Wait()}
上面的代碼片段跑了兩個(gè)協(xié)程,運(yùn)行后,觀察輸出的順序是交錯(cuò)的??赡苁牵?/p>
656612367
意味著在執(zhí)行協(xié)程A的過程中,可以隨時(shí)中斷,去執(zhí)協(xié)程行B,協(xié)程B也可能在執(zhí)行過程中中斷再去執(zhí)行協(xié)程A。
看起來協(xié)程A 和 協(xié)程B 的運(yùn)行像是線程的切換,但是請注意,這里的 A 和 B都運(yùn)行在同一個(gè)線程里面。它們的調(diào)度不是線程的切換,而是純應(yīng)用態(tài)的協(xié)程調(diào)度。
關(guān)于上述代碼中,為什么要指定下面兩行代碼?
runtime.GOMAXPROCS(1)time.Sleep(time.Second)
這需要您去看下 Go 的協(xié)程調(diào)度入門基礎(chǔ),請看我之前的另外一篇調(diào)度分析文章:
Go 的協(xié)程調(diào)度機(jī)制
如果不設(shè)置 runtime.GOMAXPROCS(1),那么程序?qū)?huì)根據(jù)操作系統(tǒng)的 CPU 核數(shù)而啟動(dòng)對應(yīng)數(shù)量的 P,導(dǎo)致多個(gè) M,即線程的啟動(dòng)。那么我們程序中的協(xié)程,就會(huì)被分配到不同的線程里面去了。為了演示,故設(shè)置數(shù)量 1,使得它們都被分配到了同一個(gè)線程里面,存于線程的協(xié)程隊(duì)列里面,等待被執(zhí)行或調(diào)度。
協(xié)程特點(diǎn)中的第 3和第 4點(diǎn)。
3. 執(zhí)行效率高。
4. 占用內(nèi)存少。
因?yàn)?mark>協(xié)程的調(diào)度切換不是線程切換,而是由程序自身控制,因此,沒有線程切換的開銷,和多線程比,線程數(shù)量越多,協(xié)程的性能優(yōu)勢就越明顯。調(diào)度發(fā)生在應(yīng)用態(tài)而非內(nèi)核態(tài)。
內(nèi)存的花銷,使用其所在的線程的內(nèi)存,意味著線程的內(nèi)存可以供多個(gè)協(xié)程使用。
其次協(xié)程的調(diào)度不需要多線程的鎖機(jī)制,因?yàn)橹挥幸粋€(gè)線程,也不存在同時(shí)寫變量沖突,所以執(zhí)行效率比多線程高很多。
協(xié)程和線程的整體對比
比較的點(diǎn) | 線程 | 協(xié)程 |
---|---|---|
數(shù)據(jù)存儲(chǔ) | 內(nèi)核態(tài)的內(nèi)存空間 | 一般是線程提供的用戶態(tài)內(nèi)存空間 |
切換操作 | 操作最終在內(nèi)核層完成,應(yīng)用層需要調(diào)用內(nèi)核層提供的 syscall 底層函數(shù) | 應(yīng)用層使用代碼進(jìn)行簡單的現(xiàn)場保存和恢復(fù)即可 |
任務(wù)調(diào)度 | 由內(nèi)核實(shí)現(xiàn),搶占方式,依賴各種鎖 | 由用戶態(tài)的實(shí)現(xiàn)的具體調(diào)度器進(jìn)行。例如 go 協(xié)程的調(diào)度器 |
語音支持程度 | 絕大部分編程語言 | 部分語言:Lua,Go,Python … |
實(shí)現(xiàn)規(guī)范 | 按照現(xiàn)代操作系統(tǒng)規(guī)范實(shí)現(xiàn) | 無統(tǒng)一規(guī)范。在應(yīng)用層由開發(fā)者實(shí)現(xiàn),高度自定義,比如只支持單線程的線程。不同的調(diào)度策略,等等 |
以上是“golang中線程和協(xié)程有哪些區(qū)別”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。