最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言并發(fā)處理的使用詳解

 更新時間:2026年03月05日 10:48:02   作者:moxiaoran5753  
Go語言通過內(nèi)置的goroutine和channel機制,實現(xiàn)了高效的并發(fā)編程,本文就來介紹一下Go語言并發(fā)處理的使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

并發(fā)是 Go 語言最核心、最亮眼的特性,Go 從語言層面原生支持并發(fā),不像 Java/Python 等語言需要依賴線程庫、協(xié)程框架,它的并發(fā)設(shè)計簡潔、輕量、高效,也是 Go 能在后端開發(fā) / 云原生領(lǐng)域脫穎而出的核心原因。

一、Go 并發(fā)的核心思想:不要通過共享內(nèi)存來通信,要通過通信來共享內(nèi)存

這是 Go 語言之父 Rob Pike 提出的并發(fā)黃金法則,也是 Go 并發(fā)設(shè)計的底層邏輯:

  • 傳統(tǒng)語言(Java/C++)并發(fā):多線程搶占共享內(nèi)存,通過 鎖(synchronized/lock) 保證數(shù)據(jù)安全,容易出現(xiàn)死鎖、競態(tài)、鎖爭用等問題;
  • Go 語言并發(fā):goroutine 之間不推薦共享內(nèi)存,而是通過專門的 channel 管道傳遞數(shù)據(jù),把數(shù)據(jù)所有權(quán)從一個 goroutine 轉(zhuǎn)移到另一個,天然避免數(shù)據(jù)競爭,代碼更安全、簡潔。

二、Go 并發(fā)的兩大基石

Go 的并發(fā)能力完全依賴兩個核心組件實現(xiàn),二者相輔相成,缺一不可:goroutine(協(xié)程) + channel(通道)

1. Goroutine (輕量級協(xié)程) - Go 并發(fā)的執(zhí)行體

(1)什么是 Goroutine

goroutine 是 Go 語言內(nèi)置的、輕量級的執(zhí)行單元,也叫「用戶級線程 / 協(xié)程」,它由 Go 運行時(runtime) 調(diào)度,而不是操作系統(tǒng)內(nèi)核調(diào)度。

(2)Goroutine 核心特點

  • 極致輕量:一個 goroutine 的初始??臻g僅 2KB,并且棧空間可以動態(tài)擴容 / 縮容(最大幾 MB),完全由 runtime 自動管理;
  • 資源占用極少:一臺普通服務(wù)器上,輕松創(chuàng)建 10 萬、甚至百萬級別的 goroutine,不會有內(nèi)存壓力;而操作系統(tǒng)線程(thread)的棧空間默認(rèn)是 1MB,創(chuàng)建幾千個線程就會內(nèi)存溢出;
  • 調(diào)度效率極高:Go 的 M/P/G 調(diào)度模型,能把 goroutine 高效映射到操作系統(tǒng)線程,調(diào)度切換的開銷只有線程的幾百分之一;
  • goroutine 是并發(fā)執(zhí)行:多個 goroutine 在同一個 Go 程序中,宏觀上 “同時運行”,微觀上由 runtime 做時間片輪轉(zhuǎn)調(diào)度。

(3)如何創(chuàng)建 Goroutine

語法超級簡單:在函數(shù)調(diào)用前加一個 go 關(guān)鍵字 即可,這個函數(shù)就會開啟一個新的 goroutine 執(zhí)行。

package main

import "fmt"

// 定義一個普通函數(shù)
func printNum(name string) {
	for i := 1; i <= 3; i++ {
		fmt.Printf("協(xié)程[%s]:輸出數(shù)字 %d\n", name, i)
	}
}

func main() {
	// 1. 開啟第一個goroutine執(zhí)行printNum
	go printNum("goroutine-1")
	// 2. 開啟第二個goroutine執(zhí)行printNum
	go printNum("goroutine-2")
	
	// 注意:主goroutine執(zhí)行完會直接退出,導(dǎo)致子goroutine來不及執(zhí)行
	// 這里簡單休眠1秒,等子goroutine執(zhí)行完畢(僅演示,生產(chǎn)不用這個方式)
	fmt.Println("主協(xié)程開始等待...")
	import "time" // 實際代碼要把import寫在頂部
	time.Sleep(time.Second)
	fmt.Println("主協(xié)程執(zhí)行結(jié)束")
}

執(zhí)行結(jié)果(順序不固定,因為 goroutine 并發(fā)調(diào)度):

主協(xié)程開始等待...

協(xié)程[goroutine-1]:輸出數(shù)字 1

協(xié)程[goroutine-2]:輸出數(shù)字 1

協(xié)程[goroutine-1]:輸出數(shù)字 2

協(xié)程[goroutine-2]:輸出數(shù)字 2

協(xié)程[goroutine-1]:輸出數(shù)字 3

協(xié)程[goroutine-2]:輸出數(shù)字 3

主協(xié)程執(zhí)行結(jié)束

(4)補充:主 Goroutine

  • 每個 Go 程序啟動后,會自動創(chuàng)建一個主 goroutine,執(zhí)行 main() 函數(shù);
  • 所有子 goroutine 由主 goroutine(或其他子 goroutine)創(chuàng)建;
  • 主 goroutine 退出,整個程序立即結(jié)束,所有子 goroutine 都會被強制終止(不管是否執(zhí)行完)。

2. Channel (通道) - Go 并發(fā)的通信方式

(1)什么是 Channel

channel 是 Go 語言提供的原生同步通信機制,可以理解為「goroutine 之間的管道」。它的核心作用:讓多個 goroutine 之間安全的傳遞數(shù)據(jù)、實現(xiàn)同步 / 協(xié)作,完全契合 Go 的并發(fā)思想:通過通信來共享內(nèi)存。

(2)Channel 核心特點

  1. 通道是類型安全的:聲明通道時必須指定傳遞的數(shù)據(jù)類型,只能傳遞對應(yīng)類型的數(shù)據(jù);
  2. 通道是阻塞特性的(核心):
    • 向一個通道發(fā)送數(shù)據(jù) ch <- data 時,如果通道滿了,發(fā)送方 goroutine 會被阻塞,直到有 goroutine 從通道取走數(shù)據(jù);
    • 從一個通道接收數(shù)據(jù) data := <-ch 時,如果通道空了,接收方 goroutine 會被阻塞,直到有 goroutine 向通道發(fā)送數(shù)據(jù);
    • 這種阻塞是 runtime 實現(xiàn)的,無額外開銷,是 goroutine 協(xié)作的核心原理;
  3. 通道可以手動關(guān)閉,關(guān)閉后無法再發(fā)送數(shù)據(jù),只能接收剩余數(shù)據(jù);
  4. 通道天然解決「數(shù)據(jù)競爭」:goroutine 之間不用共享變量,而是通過通道傳遞數(shù)據(jù),數(shù)據(jù)在 goroutine 之間 “流轉(zhuǎn)” 而非 “共享”。

(3)如何創(chuàng)建 Channel

語法:通道變量 := make(chan 數(shù)據(jù)類型, [緩沖區(qū)大小])

Channel 分為兩種:無緩沖通道有緩沖通道,通過「緩沖區(qū)大小」區(qū)分,默認(rèn)是 0(無緩沖)。

① 無緩沖通道 (同步通道)

緩沖區(qū)大小為 0,聲明時可以省略第二個參數(shù):make(chan int)

  • 特性:發(fā)送和接收必須同時就緒,否則會阻塞;
  • 本質(zhì):實現(xiàn) goroutine 之間的嚴(yán)格同步,發(fā)送方發(fā)數(shù)據(jù)的瞬間,必須有接收方在取數(shù)據(jù),相當(dāng)于 “一手交錢、一手交貨”;
  • 適用場景:goroutine 之間的強同步協(xié)作。
package main

import "fmt"

func sendData(ch chan int) {
	fmt.Println("準(zhǔn)備發(fā)送數(shù)據(jù):100")
	ch <- 100 // 發(fā)送數(shù)據(jù),無緩沖通道會阻塞,直到有g(shù)oroutine接收
	fmt.Println("數(shù)據(jù)發(fā)送成功")
}

func main() {
	// 創(chuàng)建無緩沖int類型通道
	ch := make(chan int)
	// 開啟goroutine發(fā)送數(shù)據(jù)
	go sendData(ch)
	
	// 主goroutine接收數(shù)據(jù),此時sendData的阻塞才會解除
	data := <-ch
	fmt.Printf("主協(xié)程接收數(shù)據(jù):%d\n", data)
}
② 有緩沖通道 (異步通道)

緩沖區(qū)大小為 >0 的整數(shù),比如 make(chan int, 3) 表示能存放 3 個 int 數(shù)據(jù)的通道

  • 特性:發(fā)送數(shù)據(jù)時,只要緩沖區(qū)沒滿,發(fā)送方不會阻塞;只有緩沖區(qū)滿了,發(fā)送方才會阻塞;接收數(shù)據(jù)時,只有緩沖區(qū)空了,接收方才會阻塞;
  • 本質(zhì):實現(xiàn) goroutine 之間的異步通信,可以暫存數(shù)據(jù),不用嚴(yán)格同步;
  • 適用場景:需要緩存數(shù)據(jù)、削峰填谷的并發(fā)場景。
package main

import "fmt"

func main() {
	// 創(chuàng)建有緩沖通道,緩沖區(qū)大小為2
	ch := make(chan string, 2)
	// 發(fā)送數(shù)據(jù),緩沖區(qū)未滿,不會阻塞
	ch <- "hello"
	ch <- "goroutine"
	fmt.Println("兩個數(shù)據(jù)發(fā)送成功,緩沖區(qū)已滿")

	// 接收一個數(shù)據(jù),緩沖區(qū)剩余1個
	fmt.Println("接收數(shù)據(jù):", <-ch)
	// 再發(fā)送一個數(shù)據(jù),緩沖區(qū)未滿,不會阻塞
	ch <- "channel"

	// 遍歷接收所有數(shù)據(jù)
	for i := 0; i < 2; i++ {
		fmt.Println("接收數(shù)據(jù):", <-ch)
	}
}

執(zhí)行結(jié)果:

兩個數(shù)據(jù)發(fā)送成功,

緩沖區(qū)已滿

接收數(shù)據(jù): hello

接收數(shù)據(jù): goroutine

接收數(shù)據(jù): channel

(4)Channel 的關(guān)閉與遍歷

  • 關(guān)閉通道:close(ch),只能由發(fā)送方關(guān)閉,接收方關(guān)閉會 panic;
  • 判斷通道是否關(guān)閉:接收數(shù)據(jù)時可以用 data, ok := <-ch,okfalse 表示通道已關(guān)閉且無數(shù)據(jù);
  • 遍歷通道:推薦用 for range ch,會自動遍歷通道的所有數(shù)據(jù),通道關(guān)閉后自動退出循環(huán)。
package main

import "fmt"

func sendData(ch chan int) {
	for i := 1; i <= 3; i++ {
		ch <- i // 發(fā)送數(shù)據(jù)
	}
	close(ch) // 發(fā)送完成,關(guān)閉通道
	fmt.Println("通道已關(guān)閉")
}

func main() {
	ch := make(chan int, 2)
	go sendData(ch)

	// for range 遍歷通道,自動處理關(guān)閉
	for data := range ch {
		fmt.Printf("接收數(shù)據(jù):%d\n", data)
	}
	fmt.Println("遍歷結(jié)束")
}

三、Go 并發(fā)的補充核心知識點

1. WaitGroup - 等待一組 Goroutine 執(zhí)行完成

前面的例子中,我們用 time.Sleep 等待 goroutine 執(zhí)行完畢,這是極不推薦的寫法(睡眠時間無法精準(zhǔn)控制)。

Go 的 sync 包提供了 WaitGroup,專門用來等待一組 goroutine 全部執(zhí)行完成后,再繼續(xù)執(zhí)行主 goroutine,是生產(chǎn)環(huán)境中最常用的 goroutine 等待方式。

WaitGroup 核心方法

  1. wg.Add(n):設(shè)置需要等待的 goroutine 數(shù)量,n 是 goroutine 的個數(shù);
  2. wg.Done():每個 goroutine 執(zhí)行完成后調(diào)用,相當(dāng)于 wg.Add(-1),表示完成一個;
  3. wg.Wait():主 goroutine 調(diào)用,阻塞直到所有 goroutine 都調(diào)用了 wg.Done()(計數(shù)歸 0)。

示例

package main

import (
	"fmt"
	"sync"
)

var wg sync.WaitGroup // 聲明WaitGroup

func task(name string) {
	defer wg.Done() // 函數(shù)執(zhí)行完自動調(diào)用Done,防止遺漏
	for i := 1; i <= 2; i++ {
		fmt.Printf("任務(wù)[%s]執(zhí)行:%d\n", name, i)
	}
}

func main() {
	taskNum := 3
	wg.Add(taskNum) // 需要等待3個goroutine

	// 開啟3個goroutine
	go task("goroutine-1")
	go task("goroutine-2")
	go task("goroutine-3")

	wg.Wait() // 阻塞等待所有任務(wù)完成
	fmt.Println("所有g(shù)oroutine執(zhí)行完畢,主協(xié)程退出")
}

2. Go 并發(fā) vs 傳統(tǒng)多線程并發(fā)(核心優(yōu)勢總結(jié))

很多人會問:Java 也有線程、Python 也有協(xié)程,Go 的并發(fā)到底好在哪?這里做一個清晰的對比,也是 Go 的核心競爭力:

核心結(jié)論:Go 的并發(fā)不是 “錦上添花”,而是語言層面的降維打擊,它讓并發(fā)編程的門檻大幅降低,性能大幅提升,不用關(guān)心線程池、鎖機制,就能寫出高效、安全的并發(fā)代碼。

四、Go 并發(fā)的進階內(nèi)容(拓展,按需學(xué)習(xí))

這里補充兩個進階知識點,是 Go 并發(fā)的完整體系:

1. Mutex (互斥鎖) - 共享內(nèi)存的兜底方案

Go 的設(shè)計思想是「通信優(yōu)先于共享」,但極少數(shù)場景下,goroutine 之間必須共享變量(比如全局計數(shù)器),此時可以用 sync.Mutex 互斥鎖保證數(shù)據(jù)安全。

  • mutex.Lock():加鎖,同一時間只有一個 goroutine 能獲取鎖;
  • mutex.Unlock():解鎖,釋放鎖資源;
  • 注意:盡量少用鎖,鎖會帶來競態(tài)、死鎖風(fēng)險,能用 channel 解決的問題,堅決不用鎖。

2. Select - 多路復(fù)用通道

select 是 Go 的關(guān)鍵字,專門用來同時監(jiān)聽多個 channel 的讀寫操作,實現(xiàn)多路并發(fā)控制,類似 Linux 的 IO 多路復(fù)用。

  • 特性:select 會隨機選擇一個就緒的 case 執(zhí)行;如果所有 case 都阻塞,會阻塞到有 case 就緒;
  • 適用場景:同時處理多個通道、設(shè)置通道超時、非阻塞讀寫通道等。

總結(jié)

  1. Go 并發(fā)的核心思想:不要通過共享內(nèi)存來通信,要通過通信來共享內(nèi)存;
  2. Go 并發(fā)的兩大基石:goroutine(輕量級協(xié)程,并發(fā)執(zhí)行體) + channel(通道,協(xié)程間通信方式);
  3. Goroutine:輕量(2KB 棧)、高效、百萬級創(chuàng)建,runtime 調(diào)度,主協(xié)程退出則程序結(jié)束;
  4. Channel:類型安全、阻塞特性,分無緩沖(同步)和有緩沖(異步),是 goroutine 的安全通信方式;
  5. 等待 goroutine 完成:用 sync.WaitGroup禁止用 time.Sleep;
  6. Go 并發(fā)的核心優(yōu)勢:相比傳統(tǒng)多線程,資源占用更少、調(diào)度更快、代碼更簡潔、數(shù)據(jù)更安全;
  7. 進階兜底:必須共享變量時用 sync.Mutex,多路通道控制用 select。

到此這篇關(guān)于Go語言并發(fā)處理的使用詳解的文章就介紹到這了,更多相關(guān)Go語言 并發(fā)處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言循環(huán)遍歷含有中文的字符串的方法小結(jié)

    Go語言循環(huán)遍歷含有中文的字符串的方法小結(jié)

    這篇文章主要介紹了Go語言循環(huán)遍歷含有中文的字符串的幾種方法,文章通過代碼示例講解的非常詳細,具有一定的參考價值,感興趣的小伙伴跟著小編一起來看看吧
    2023-07-07
  • Go語言針對Map的11問你知道幾個?

    Go語言針對Map的11問你知道幾個?

    Go?Map?的?11?連問,你頂?shù)昧寺?這篇文章小編為大家準(zhǔn)備了?Go?語言?Map?的?11?連問,相信大家看完肯定會有幫助的,感興趣的小伙伴可以收藏一波
    2023-05-05
  • 使用Go語言進行條件編譯的示例代碼

    使用Go語言進行條件編譯的示例代碼

    Go的條件編譯主要通過構(gòu)建標(biāo)簽(build?tags)和構(gòu)建約束(build?constraints)來實現(xiàn),這些標(biāo)簽和約束可以讓我們針對不同的操作系統(tǒng)、架構(gòu)或特定條件編寫特定代碼,本文給大家介紹了如何使用Go語言進行條件編譯,需要的朋友可以參考下
    2024-06-06
  • 深入解析Go語言編程中的遞歸使用

    深入解析Go語言編程中的遞歸使用

    這篇文章主要介紹了Go語言編程中的遞歸使用,是Go語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-11-11
  • GoLang并發(fā)機制探究goroutine原理詳細講解

    GoLang并發(fā)機制探究goroutine原理詳細講解

    goroutine是Go語言提供的語言級別的輕量級線程,在我們需要使用并發(fā)時,我們只需要通過 go 關(guān)鍵字來開啟 goroutine 即可。這篇文章主要介紹了GoLang并發(fā)機制goroutine原理,感興趣的可以了解一下
    2022-12-12
  • Go中的關(guān)鍵字any interface是否會成為歷史

    Go中的關(guān)鍵字any interface是否會成為歷史

    這篇文章主要為大家介紹了Go中的關(guān)鍵字any interface是否會成為歷史的講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • 詳解golang中make與new的異同點和用法

    詳解golang中make與new的異同點和用法

    這篇文章將給大家介紹了go語言中函數(shù)new與make的使用和區(qū)別,關(guān)于go語言中new和make是內(nèi)建的兩個函數(shù),主要用來創(chuàng)建分配類型內(nèi)存,文中通過代碼示例介紹的非常詳細,具有一定的參考價值,需要的朋友可以參考下
    2024-01-01
  • go 迭代string數(shù)組操作 go for string[]

    go 迭代string數(shù)組操作 go for string[]

    這篇文章主要介紹了go 迭代string數(shù)組操作 go for string[],具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • GoLang之go build命令的具體使用

    GoLang之go build命令的具體使用

    本文主要介紹了GoLang之go build命令的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • go?tar包歸檔文件處理操作全面指南

    go?tar包歸檔文件處理操作全面指南

    這篇文章主要為大家介紹了使用go?tar包歸檔文件處理操作全面指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12

最新評論

内丘县| 成安县| 富蕴县| 青川县| 广州市| 龙胜| 尉犁县| 肇州县| 钦州市| 青海省| 库伦旗| 通榆县| 依安县| 政和县| 延津县| 聊城市| 平阴县| 郯城县| 建瓯市| 化德县| 阿荣旗| 麻江县| 青神县| 禹城市| 张家口市| 调兵山市| SHOW| 本溪| 青铜峡市| 城口县| 休宁县| 丹凤县| 林口县| 普安县| 南通市| 景宁| 上高县| 库伦旗| 广水市| 全州县| 阿荣旗|