golang并發(fā)編程中Goroutine 協(xié)程的實(shí)現(xiàn)
Go 協(xié)程(Goroutine)是 Go 語(yǔ)言提供的一種輕量級(jí)線程,由 Go 運(yùn)行時(shí)來(lái)管理。是與其他函數(shù)同時(shí)運(yùn)行的函數(shù),它們是并發(fā)執(zhí)行代碼的基礎(chǔ)。
在函數(shù)調(diào)用前加上 go 關(guān)鍵字,這次調(diào)用就會(huì)在一個(gè)新的 goroutine 中并發(fā)執(zhí)行。當(dāng)被調(diào)用的函數(shù)返回時(shí),這個(gè) goroutine 也自動(dòng)結(jié)束。
需要注意的是,如果這個(gè)函數(shù)有返回值,那么這個(gè)返回值會(huì)被丟棄。
Go 協(xié)程(Goroutine)之間通過(guò)通道(channel)進(jìn)行通信,簡(jiǎn)單的說(shuō)就是多個(gè)協(xié)程之間通信的管道。通道可以防止多個(gè)協(xié)程訪問(wèn)共享內(nèi)存時(shí)發(fā)生資源爭(zhēng)搶的問(wèn)題。
啟動(dòng) Goroutine
要啟動(dòng)一個(gè)新的 Goroutine,只需要在函數(shù)調(diào)用前加上 go
關(guān)鍵字。例如:
這行代碼會(huì)啟動(dòng)一個(gè)新的 Goroutine 來(lái)執(zhí)行 myFunction
。
Goroutine 的特性
- 輕量級(jí):Goroutine 比傳統(tǒng)線程更輕量級(jí)。每個(gè) Goroutine 使用的內(nèi)存非常少,啟動(dòng)速度也更快。
- 調(diào)度:Goroutine 由 Go 運(yùn)行時(shí)管理和調(diào)度,而不是操作系統(tǒng)。
- 棧管理:Goroutine 的棧是動(dòng)態(tài)增長(zhǎng)的,初始大小一般較?。ㄈ?2KB),但可以根據(jù)需要?jiǎng)討B(tài)擴(kuò)展,最大可達(dá) 1GB。
同步和通信
在 Go 中,同步和通信通常通過(guò)通道(channel)來(lái)實(shí)現(xiàn)。通道是 Go 語(yǔ)言提供的一種類型安全的通信機(jī)制。
創(chuàng)建通道
可以使用 make
函數(shù)創(chuàng)建通道:
發(fā)送和接收
使用 <-
操作符可以發(fā)送和接收數(shù)據(jù):
// 發(fā)送數(shù)據(jù)到通道 ch <- 42 // 從通道接收數(shù)據(jù) value := <-ch
帶緩沖的通道
創(chuàng)建帶緩沖的通道:
ch := make(chan int, 100)
這樣通道可以在不阻塞發(fā)送 Goroutine 的情況下緩沖一定數(shù)量的數(shù)據(jù)。
示例代碼
以下是一個(gè)簡(jiǎn)單的 Goroutine 和通道的示例:
package main import ( "fmt" "time" ) func worker(ch chan int) { for i := 0; i < 5; i++ { ch <- i time.Sleep(time.Second) } close(ch) } func main() { ch := make(chan int) go worker(ch) for val := range ch { fmt.Println(val) } }
在這個(gè)例子中,worker
函數(shù)向通道 ch
發(fā)送數(shù)據(jù),然后 main
函數(shù)從通道 ch
接收數(shù)據(jù)并打印。
Goroutines 和主程序
需要注意的是,如果主程序退出,所有未完成的 Goroutines 也會(huì)立即終止。因此,通常需要確保主程序等待所有 Goroutines 完成。例如,可以使用 sync.WaitGroup
來(lái)實(shí)現(xiàn)這一點(diǎn):
package main import ( "fmt" "sync" ) func worker(wg *sync.WaitGroup, id int) { defer wg.Done() fmt.Printf("Worker %d starting\n", id) // 模擬工作 time.Sleep(time.Second) fmt.Printf("Worker %d done\n", id) } func main() { var wg sync.WaitGroup for i := 1; i <= 5; i++ { wg.Add(1) go worker(&wg, i) } wg.Wait() fmt.Println("All workers done") }
這個(gè)示例使用 sync.WaitGroup
來(lái)等待所有的 Goroutines 完成。wg.Add(1)
用于增加計(jì)數(shù),wg.Done()
在 Goroutine 完成時(shí)減少計(jì)數(shù),wg.Wait()
則阻塞直到所有的 Goroutines 完成。
協(xié)程、線程、進(jìn)程
協(xié)程、線程和進(jìn)程是并發(fā)和并行編程中的三種主要概念。它們有不同的特性和適用場(chǎng)景,以下是它們的主要區(qū)別:
進(jìn)程 (Process)
定義:
- 進(jìn)程是操作系統(tǒng)中資源分配的基本單位。
- 每個(gè)進(jìn)程都有自己的內(nèi)存空間、文件描述符和其他資源。
特點(diǎn):
- 隔離性:進(jìn)程之間是相互獨(dú)立的,一個(gè)進(jìn)程的崩潰不會(huì)影響其他進(jìn)程。
- 開銷大:進(jìn)程之間切換的開銷較大,需要保存和恢復(fù)大量上下文信息。
- 通信復(fù)雜:進(jìn)程間通信(IPC,如管道、消息隊(duì)列、共享內(nèi)存等)相對(duì)復(fù)雜。
適用場(chǎng)景:
- 適用于需要高度隔離和獨(dú)立運(yùn)行的任務(wù)。
- 適用于不同編程語(yǔ)言和不同平臺(tái)之間的并發(fā)處理。
線程 (Thread)
定義:
- 線程是進(jìn)程中的一個(gè)執(zhí)行單元,屬于進(jìn)程的一部分。
- 同一進(jìn)程中的線程共享該進(jìn)程的內(nèi)存和其他資源。
特點(diǎn):
- 輕量級(jí):相比進(jìn)程,線程的創(chuàng)建和切換開銷較小。
- 共享資源:同一進(jìn)程內(nèi)的線程可以直接訪問(wèn)共享的內(nèi)存和資源,但也因此帶來(lái)了同步問(wèn)題。
- 并發(fā)執(zhí)行:多個(gè)線程可以在多核 CPU 上并發(fā)執(zhí)行。
適用場(chǎng)景:
- 適用于需要并行處理的任務(wù),如多線程服務(wù)器、并行計(jì)算等。
- 適用于需要頻繁切換和低開銷的場(chǎng)景。
協(xié)程 (Coroutine)
定義:
- 協(xié)程是一種用戶態(tài)的輕量級(jí)線程,也稱為微線程或纖程。
- 協(xié)程由程序自身管理調(diào)度,而不是操作系統(tǒng)。
特點(diǎn):
- 更輕量級(jí):協(xié)程的創(chuàng)建和切換開銷更小,因?yàn)椴簧婕皟?nèi)核態(tài)的切換。
- 協(xié)作式調(diào)度:協(xié)程通過(guò)顯式的讓出操作(如
yield
)來(lái)切換,控制權(quán)由程序員掌握。 - 共享內(nèi)存:同一線程內(nèi)的協(xié)程可以共享內(nèi)存,但需要注意同步問(wèn)題。
適用場(chǎng)景:
- 適用于 I/O 密集型任務(wù),如高并發(fā)網(wǎng)絡(luò)服務(wù)器。
- 適用于需要大量并發(fā)但對(duì)并行性要求不高的場(chǎng)景,如爬蟲、異步編程等。
總結(jié)
- 進(jìn)程:資源隔離好,開銷大,適用于獨(dú)立運(yùn)行的任務(wù)。
- 線程:資源共享,開銷較小,適用于需要并行處理的任務(wù)。
- 協(xié)程:更輕量級(jí),用戶態(tài)調(diào)度,適用于大量并發(fā)的 I/O 密集型任務(wù)。
各自的選擇主要取決于具體的應(yīng)用場(chǎng)景和性能需求。協(xié)程在現(xiàn)代編程中越來(lái)越受歡迎,尤其是在需要高并發(fā)和高效 I/O 操作的場(chǎng)景中。
到此這篇關(guān)于golang并發(fā)編程中Goroutine 協(xié)程的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)golang Goroutine 協(xié)程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- golang gin 框架 異步同步 goroutine 并發(fā)操作
- Go語(yǔ)言中的并發(fā)goroutine底層原理
- Go并發(fā)編程之goroutine使用正確方法
- Go 并發(fā)編程Goroutine的實(shí)現(xiàn)示例
- Golang 語(yǔ)言控制并發(fā) Goroutine的方法
- Go中Goroutines輕量級(jí)并發(fā)的特性及效率探究
- 使用Go?goroutine實(shí)現(xiàn)并發(fā)的Clock服務(wù)
- Go語(yǔ)言使用goroutine及通道實(shí)現(xiàn)并發(fā)詳解
- Go 控制協(xié)程(goroutine)的并發(fā)數(shù)量
- Go語(yǔ)言使用Goroutine并發(fā)打印的項(xiàng)目實(shí)踐
相關(guān)文章
Go語(yǔ)言WaitGroup使用時(shí)需要注意的坑
Go語(yǔ)言中WaitGroup的用途是它能夠一直等到所有的goroutine執(zhí)行完成,并且阻塞主線程的執(zhí)行,直到所有的goroutine執(zhí)行完成。之前一直使用也沒(méi)有問(wèn)題,但最近通過(guò)同事的一段代碼引起了關(guān)于WaitGroup的注意,下面這篇文章就介紹了WaitGroup使用時(shí)需要注意的坑及填坑。2016-12-12Golang如何編寫內(nèi)存高效及CPU調(diào)優(yōu)的Go結(jié)構(gòu)體
這篇文章主要介紹了Golang如何編寫內(nèi)存高效及CPU調(diào)優(yōu)的Go結(jié)構(gòu)體,結(jié)構(gòu)體是包含多個(gè)字段的集合類型,用于將數(shù)據(jù)組合為記錄2022-07-07Golang實(shí)現(xiàn)請(qǐng)求限流的幾種辦法(小結(jié))
這篇文章主要介紹了Golang實(shí)現(xiàn)請(qǐng)求限流的幾種辦法(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10Golang?流水線設(shè)計(jì)模式實(shí)踐示例詳解
這篇文章主要為大家介紹了Golang?流水線設(shè)計(jì)模式實(shí)踐示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12使用Go實(shí)現(xiàn)偽靜態(tài)URL重寫功能
在Web開發(fā)中,偽靜態(tài)URL已成為優(yōu)化網(wǎng)站架構(gòu)和提升SEO的常用技術(shù)手段,偽靜態(tài)URL是一種介于動(dòng)態(tài)URL和靜態(tài)URL之間的解決方案,本文給大家介紹了如何使用Go實(shí)現(xiàn)偽靜態(tài)URL重寫功能,需要的朋友可以參考下2024-08-08go語(yǔ)言題解LeetCode228匯總區(qū)間示例詳解
這篇文章主要為大家介紹了go語(yǔ)言題解LeetCode228匯總區(qū)間示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12使用gopacket解析協(xié)議層中的相關(guān)數(shù)據(jù)方式
文章介紹使用Wireshark抓取ping數(shù)據(jù)包并保存為pcap格式,通過(guò)Go語(yǔ)言gopacket解析,提取IP版本號(hào)、指定標(biāo)識(shí)的數(shù)據(jù)包長(zhǎng)度及應(yīng)用層ICMP字符串內(nèi)容,展示TCP/IP協(xié)議族解析的簡(jiǎn)便方法2025-07-07Go語(yǔ)言使用context控制協(xié)程取消的方法步驟
本文將通過(guò)一個(gè)實(shí)際案例,使用?context?控制協(xié)程的取消,避免資源泄露,實(shí)現(xiàn)優(yōu)雅退出,具有一定的參考價(jià)值,感興趣的可以了解一下2025-08-08