Go并發(fā):Goroutine
1.并發(fā)基礎(chǔ)概念:進(jìn)程、線程、協(xié)程
(1) 進(jìn)程
可以比作食材加工的一系列動(dòng)作
進(jìn)程就是程序在操作系統(tǒng)中的一次執(zhí)行過(guò)程,是由系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位,進(jìn)程是一個(gè)動(dòng)態(tài)概念,是程序在執(zhí)行過(guò)程中分配和管理資源的基本單位,每一個(gè)進(jìn)程都有一個(gè)自己的地址空間。一個(gè)進(jìn)程至少有5種基本狀態(tài):初始態(tài)、執(zhí)行態(tài)、等待狀態(tài)、就緒狀態(tài)、終止?fàn)顟B(tài)。
通俗講: 進(jìn)程就是一個(gè)正在執(zhí)行的程序。
[一般情況] 一個(gè)程序一個(gè)進(jìn)程
[多進(jìn)程]] 一個(gè)程序多個(gè)進(jìn)程
可以在終端輸入以下內(nèi)容,來(lái)列出所有的進(jìn)程
ps -A
比如在Windows系統(tǒng)中,一個(gè)運(yùn)行的xx.exe就是一個(gè)進(jìn)程。
(2) 線程
可以比作食材加工的某一個(gè)動(dòng)作
線程是運(yùn)算調(diào)度的最小單元,是進(jìn)程中的一個(gè)執(zhí)行任務(wù)(控制單元),負(fù)責(zé)當(dāng)前進(jìn)程中程序的執(zhí)行。一個(gè)進(jìn)程至少有一個(gè)線程,一個(gè)進(jìn)程可以運(yùn)行多個(gè)線程,多個(gè)線程可共享數(shù)據(jù)。
進(jìn)程與線程的區(qū)別如下
根本區(qū)別:進(jìn)程是操作系統(tǒng)資源分配的基本單位,而線程是處理器任務(wù)調(diào)度和執(zhí)行的基本單位
資源開(kāi)銷:每個(gè)進(jìn)程都有獨(dú)立的代碼和數(shù)據(jù)空間(程序上下文),程序之間的切換會(huì)有較大的開(kāi)銷;線程可以看做輕量級(jí)的進(jìn)程,同一類線程共享代碼和數(shù)據(jù)空間,每個(gè)線程都有自己獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器(PC),線程之間切換的開(kāi)銷小。
包含關(guān)系:如果一個(gè)進(jìn)程內(nèi)有多個(gè)線程,則執(zhí)行過(guò)程不是一條線的,而是多條線(線程)共同完成的;線程是進(jìn)程的一部分,所以線程也被稱為輕權(quán)進(jìn)程或者輕量級(jí)進(jìn)程。
內(nèi)存分配:同一進(jìn)程的線程共享本進(jìn)程的地址空間和資源,而進(jìn)程之間的地址空間和資源是相互獨(dú)立的
影響關(guān)系:一個(gè)進(jìn)程崩潰后,在保護(hù)模式下不會(huì)對(duì)其他進(jìn)程產(chǎn)生影響,但是一個(gè)線程崩潰整個(gè)進(jìn)程都死掉。所以多進(jìn)程要比多線程健壯。
執(zhí)行過(guò)程:每個(gè)獨(dú)立的進(jìn)程有程序運(yùn)行的入口、順序執(zhí)行序列和程序出口。但是線程不能獨(dú)立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個(gè)線程執(zhí)行控制,兩者均可并發(fā)執(zhí)行
查看線程
- 進(jìn)入
terminal
- 輸入命令
ps-M[pid]
- 查看對(duì)應(yīng)
pid
線程
(3) 協(xié)程
協(xié)程(goroutine) 是輕量級(jí)的執(zhí)行線程。
實(shí)操
假設(shè)我們有一個(gè)函數(shù)叫做 action()
。 我們一般會(huì)這樣 同步地
調(diào)用它使用 go action()
在一個(gè)協(xié)程中調(diào)用這個(gè)函數(shù)。 這個(gè)新的 Go 協(xié)程將會(huì) 并發(fā)地
執(zhí)行這個(gè)函數(shù)。
package main
import (
"fmt"
// "time"
)
func action() {
fmt.Println("Test Goroutine")
}
func main() {
go action()
// time.Sleep(2 * time.Second)
}
可見(jiàn)咩有任何輸出,把注釋內(nèi)容取消注釋再運(yùn)行
為什么要沉睡?
go 語(yǔ)言運(yùn)行非???,若沒(méi)有沉睡,可能會(huì)導(dǎo)致
“協(xié)程還沒(méi)有執(zhí)行完,
main
函數(shù)已經(jīng)結(jié)束了”最終導(dǎo)致協(xié)程結(jié)束前,
main
函數(shù)已經(jīng)被銷毀因此我們需要讓主進(jìn)程去等待一定時(shí)間的子協(xié)程,才能得到子協(xié)程的輸出
2.多協(xié)程核心機(jī)理
步驟
- 任務(wù)切片/分配
- 啟動(dòng)多個(gè)協(xié)程
- 合并多個(gè)協(xié)程結(jié)果
使用場(chǎng)景
- 運(yùn)算量比較多
- 協(xié)程間依賴性比較弱
3.多協(xié)程等待實(shí)操
我們可以使用通道來(lái)同步協(xié)程之間的執(zhí)行狀態(tài)。使用 wait group 等待多個(gè)協(xié)程完成
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 2; i ++ {
wg.Add(1)
go func(num int) {
fmt.Printf("Goroutine Test %d\n", num)
wg.Done()
}(i)
}
wg.Wait()
}
更多細(xì)節(jié)清查閱
waitgroup
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-815154.htmlGo by Example 中文版: WaitGroup (gobyexample-cn.github.io)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-815154.html
到了這里,關(guān)于Go并發(fā)快速入門(mén):Goroutine的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!