Go進階高并發(多線程)處理教程

Go進階高并發處理教程

目錄

  1. Go并發編程基礎
  2. Goroutine深入理解
  3. 同步原語詳解
  4. 并發模式與最佳實踐
  5. 性能優化技巧
  6. 實戰案例

Go并發編程基礎

什么是并發?

并發是指程序能夠同時處理多個任務的能力。Go語言從設計之初就將并發作為核心特性,提供了簡潔而強大的并發編程模型。

Go并發模型的優勢

  • 輕量級協程:Goroutine比傳統線程更輕量
  • CSP模型:通過通信來共享內存,而不是通過共享內存來通信
  • 內置調度器:Go運行時自動管理goroutine的調度

Goroutine深入理解

創建和啟動Goroutine

package mainimport ("fmt""time"
)func worker(id int) {fmt.Printf("Worker %d starting\n", id)time.Sleep(time.Second)fmt.Printf("Worker %d done\n", id)
}func main() {// 啟動多個goroutinefor i := 1; i <= 5; i++ {go worker(i)}// 等待所有goroutine完成time.Sleep(2 * time.Second)fmt.Println("All workers completed")
}

Goroutine的生命周期

  1. 創建:使用go關鍵字創建
  2. 調度:由Go調度器管理
  3. 執行:在可用的OS線程上執行
  4. 結束:函數返回時自動結束

調度器工作原理

Go使用M:N調度模型:

  • M:OS線程(Machine)
  • P:處理器(Processor)
  • G:Goroutine
G1  G2  G3  G4\   |   |  /\  |   | /\ |   |/\|   |P1  P2|   |M1  M2

同步原語詳解

sync.WaitGroup

用于等待一組goroutine完成:

package mainimport ("fmt""sync""time"
)func worker(id int, wg *sync.WaitGroup) {defer wg.Done() // 完成時調用Done()fmt.Printf("Worker %d starting\n", id)time.Sleep(time.Second)fmt.Printf("Worker %d done\n", id)
}func main() {var wg sync.WaitGroupfor i := 1; i <= 5; i++ {wg.Add(1) // 增加等待計數go worker(i, &wg)}wg.Wait() // 等待所有goroutine完成fmt.Println("All workers completed")
}

sync.Mutex

互斥鎖用于保護共享資源:

package mainimport ("fmt""sync"
)type Counter struct {mu    sync.Mutexvalue int
}func (c *Counter) Increment() {c.mu.Lock()defer c.mu.Unlock()c.value++
}func (c *Counter) Value() int {c.mu.Lock()defer c.mu.Unlock()return c.value
}func main() {counter := &Counter{}var wg sync.WaitGroup// 啟動100個goroutine同時增加計數器for i := 0; i < 100; i++ {wg.Add(1)go func() {defer wg.Done()for j := 0; j < 1000; j++ {counter.Increment()}}()}wg.Wait()fmt.Printf("Final counter value: %d\n", counter.Value())
}

sync.RWMutex

讀寫鎖允許多個讀操作同時進行:

type SafeMap struct {mu sync.RWMutexdata map[string]int
}func (sm *SafeMap) Get(key string) (int, bool) {sm.mu.RLock()defer sm.mu.RUnlock()val, ok := sm.data[key]return val, ok
}func (sm *SafeMap) Set(key string, value int) {sm.mu.Lock()defer sm.mu.Unlock()sm.data[key] = value
}

sync.Once

確保某個操作只執行一次:

package mainimport ("fmt""sync"
)var once sync.Once
var instance *Singletontype Singleton struct {data string
}func GetInstance() *Singleton {once.Do(func() {fmt.Println("Creating singleton instance")instance = &Singleton{data: "singleton"}})return instance
}func main() {var wg sync.WaitGroupfor i := 0; i < 10; i++ {wg.Add(1)go func(id int) {defer wg.Done()s := GetInstance()fmt.Printf("Goroutine %d got instance: %s\n", id, s.data)}(i)}wg.Wait()
}

并發模式與最佳實踐

Worker Pool模式

package mainimport ("fmt""sync""time"
)type Job struct {ID   intData string
}type Result struct {Job    JobOutput string
}func worker(id int, jobs <-chan Job, results chan<- Result, wg *sync.WaitGroup) {defer wg.Done()for job := range jobs {fmt.Printf("Worker %d processing job %d\n", id, job.ID)time.Sleep(time.Millisecond * 100) // 模擬工作result := Result{Job:    job,Output: fmt.Sprintf("Processed by worker %d", id),}results <- result}
}func main() {const numWorkers = 3const numJobs = 10jobs := make(chan Job, numJobs)results := make(chan Result, numJobs)var wg sync.WaitGroup// 啟動workerfor i := 1; i <= numWorkers; i++ {wg.Add(1)go worker(i, jobs, results, &wg)}// 發送任務for i := 1; i <= numJobs; i++ {jobs <- Job{ID: i, Data: fmt.Sprintf("data-%d", i)}}close(jobs)// 等待所有worker完成go func() {wg.Wait()close(results)}()// 收集結果for result := range results {fmt.Printf("Job %d result: %s\n", result.Job.ID, result.Output)}
}

扇入扇出模式

// 扇出:將工作分發給多個goroutine
func fanOut(input <-chan int, workers int) []<-chan int {outputs := make([]<-chan int, workers)for i := 0; i < workers; i++ {output := make(chan int)outputs[i] = outputgo func(out chan<- int) {defer close(out)for n := range input {out <- n * n // 計算平方}}(output)}return outputs
}// 扇入:將多個channel的結果合并
func fanIn(inputs ...<-chan int) <-chan int {output := make(chan int)var wg sync.WaitGroupfor _, input := range inputs {wg.Add(1)go func(in <-chan int) {defer wg.Done()for n := range in {output <- n}}(input)}go func() {wg.Wait()close(output)}()return output
}

性能優化技巧

1. 合理設置GOMAXPROCS

import "runtime"func init() {// 設置使用的CPU核心數runtime.GOMAXPROCS(runtime.NumCPU())
}

2. 避免goroutine泄漏

// 錯誤示例:可能導致goroutine泄漏
func badExample() {ch := make(chan int)go func() {ch <- 1 // 如果沒有接收者,這個goroutine會永遠阻塞}()// 函數返回,但goroutine仍在運行
}// 正確示例:使用context控制goroutine生命周期
func goodExample(ctx context.Context) {ch := make(chan int, 1) // 使用緩沖channelgo func() {select {case ch <- 1:case <-ctx.Done():return}}()
}

3. 使用對象池減少GC壓力

import "sync"var pool = sync.Pool{New: func() interface{} {return make([]byte, 1024)},
}func processData(data []byte) {buf := pool.Get().([]byte)defer pool.Put(buf)// 使用buf處理數據
}

實戰案例

并發HTTP客戶端

package mainimport ("fmt""net/http""sync""time"
)type Result struct {URL        stringStatusCode intDuration   time.DurationError      error
}func fetchURL(url string, results chan<- Result, wg *sync.WaitGroup) {defer wg.Done()start := time.Now()resp, err := http.Get(url)duration := time.Since(start)result := Result{URL:      url,Duration: duration,Error:    err,}if err == nil {result.StatusCode = resp.StatusCoderesp.Body.Close()}results <- result
}func main() {urls := []string{"https://www.google.com","https://www.github.com","https://www.stackoverflow.com","https://www.golang.org",}results := make(chan Result, len(urls))var wg sync.WaitGroup// 并發請求所有URLfor _, url := range urls {wg.Add(1)go fetchURL(url, results, &wg)}// 等待所有請求完成go func() {wg.Wait()close(results)}()// 處理結果for result := range results {if result.Error != nil {fmt.Printf("Error fetching %s: %v\n", result.URL, result.Error)} else {fmt.Printf("%s: %d (%v)\n", result.URL, result.StatusCode, result.Duration)}}
}

總結

Go語言的并發編程提供了強大而簡潔的工具:

  1. Goroutine:輕量級協程,易于創建和管理
  2. Channel:類型安全的通信機制
  3. sync包:提供各種同步原語
  4. 并發模式:Worker Pool、扇入扇出等經典模式

掌握這些概念和技巧,能夠幫助您構建高性能、可擴展的并發應用程序。記住Go的并發哲學:通過通信來共享內存,而不是通過共享內存來通信

參考資源

  • Go官方文檔 - 并發
  • Go并發模式
  • Go內存模型

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/92709.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/92709.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/92709.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

一種基于單片機控制的太陽能電池板系統設計

摘 要: 設計的太陽能電池板系統&#xff0c;以單片機單元為核心&#xff0c;集檢測、光能跟蹤、板面清潔、輸出控制為一體&#xff0c;解決了傳統太陽能板控制功能簡單、效率低的技術問題&#xff0c;達到了自動監測輸出電能、自動清洗板面、全方位跟蹤光伏發電最大效率點的技術…

前端實現類瀏覽器的 Ctrl+F 全局搜索功能(Vue2 + mark.js,用于Electron 、QT等沒有瀏覽器Ctrl+F全局搜索功能的殼子中)

&#x1f4bb; 在 Electron 中實現類瀏覽器的 CtrlF 全局搜索功能&#xff08;Vue2 mark.js&#xff09;本文介紹如何在 Electron 應用中構建一個像 Chrome 一樣的 CtrlF 查找框&#xff0c;支持全局高亮、滾動定位、關鍵詞計數與上下跳轉。? 背景 在網頁瀏覽器中&#xff0c…

詳解力扣高頻 SQL 50 題-1757.可回收且低脂的產品【入門】

傳送門&#xff1a;可回收且低脂的產品 題目 表&#xff1a;Products -------------------- | Column Name | Type | -------------------- | product_id | int | | low_fats | enum | | recyclable | enum | -------------------- product_id 是該表的主鍵&#xff08;具有…

CSS3 網格元素

CSS3 網格元素&#xff08;Grid Items&#xff09;是網格容器&#xff08;Grid Container&#xff09;的直接子元素&#xff0c;它們參與 CSS 網格布局&#xff0c;并根據網格容器的規則在網格中定位和排列。以下是對網格元素的詳細中文講解&#xff0c;涵蓋定義、相關屬性、用…

30天打牢數模基礎-決策樹講解

案例代碼一、代碼說明本代碼針對員工離職預測問題&#xff0c;使用CART決策樹算法&#xff08;基尼指數&#xff09;實現分類&#xff0c;并包含特征重要性評估和樹結構可視化。數據為模擬的10個員工樣本&#xff0c;特征包括工作年限、月薪、是否加班、團隊氛圍評分&#xff0…

React與jQuery全棧實戰指南

以下是為React工程師優化的jQuery全棧指南&#xff0c;結合Thymeleaf項目需求與React思維模式&#xff0c;整合核心概念、避坑策略及實戰技巧。內容依據官方文檔與多篇技術文章優化補充&#xff0c;保留原有框架并深化關鍵細節&#xff1a; ?一、jQuery核心設計哲學 vs React?…

Redis分布式鎖的學習(八)

一、分布式鎖 1.1、分布式鎖是什么&#xff1f; 是一種在分布式系統中協調多個進程/服務對共享資源進行互斥訪問的機制&#xff1b;確保在任意時刻&#xff0c;只有一個客戶端可以訪問資源。 1.2、為什么需要分布式鎖&#xff1f; 解決多個服務/進程對同共享資源競爭&…

spring的常用注解匯總

在 Spring 和 Spring Boot 框架中&#xff0c;有許多核心注解被廣泛應用。以下是常用的關鍵注解分類詳解&#xff1a;一、組件聲明與依賴注入注解作用示例Component通用組件聲明 (Bean 的泛化形式)Component public class ServiceImpl {...}Service標記服務層&#xff08;業務邏…

Claude4、GPT4、Kimi K2、Gemini2.5、DeepSeek R1、Code Llama等2025主流AI編程大模型多維度對比分析報告

2025主流AI編程大模型多維度對比分析報告引言&#xff1a;AI編程大模型的技術格局與選型挑戰一、核心模型概覽&#xff1a;技術定位與市場份額1.國際第一梯隊&#xff08;1&#xff09;Claude 4系列&#xff08;Anthropic&#xff09;&#xff08;2&#xff09;GPT-4.1&#xf…

Overleaf中下載.aux和.bbl文件

有些會議提交終稿的時候&#xff0c;可能會讓上傳.bbl和.aux文件&#xff0c;但是使用Overleaf下載下來的壓縮包中缺沒有這些文件在網上搜了一下都是用的舊版的Overleaf的教程&#xff0c;或者教程比較繁瑣&#xff0c;其實新版的Overleaf也可以直接下載 打開你的論文編譯好&am…

uniapp寫app做測試手機通知欄展示內容

uniapp寫app做測試手機通知欄展示內容 以下代碼&#xff1a;只是個簡單測試能不能給手機發送消息&#xff0c;能不能引導打開通知權限&#xff0c;能不能進行跳轉的功能, 增加 notify.js 以下文件 // 模擬本地通知功能 export function showNotification() {// 1. 檢查通知…

分布式云計算:未來計算架構的全新演進

隨著信息技術的不斷發展,尤其是云計算技術的飛速進步,企業和個人對計算資源的需求已經從傳統的單一數據中心向更為靈活、可擴展的分布式架構轉變。分布式云計算作為一種新興的云計算模型,旨在將計算資源和數據存儲分布在多個地理位置上,從而提供更加高效、安全和可靠的服務…

2025年海外短劇獨立站開發:H5+PC端雙平臺技術實踐與增長策略

引言在全球化內容消費浪潮下&#xff0c;海外短劇市場正經歷爆發式增長。據DataEye《2025H1海外微短劇行業數據報告》顯示&#xff0c;2025年海外短劇市場規模預計突破45億美元&#xff0c;其中東南亞、拉美等新興市場貢獻超30%增量。本文將以某頭部短劇平臺的雙平臺開發實踐為…

OpenAI發布ChatGPT Agent,AI智能體迎來關鍵變革

注&#xff1a;此文章內容均節選自充電了么創始人&#xff0c;CEO兼CTO陳敬雷老師的新書《GPT多模態大模型與AI Agent智能體》&#xff08;跟我一起學人工智能&#xff09;【陳敬雷編著】【清華大學出版社】 清華《GPT多模態大模型與AI Agent智能體》書籍配套視頻課程【陳敬雷…

企業級安全威脅檢測與響應(EDR/XDR)架構設計

在這個網絡威脅如洪水猛獸的時代&#xff0c;企業的安全防護不能再像守城門的老大爺一樣只會喊"什么人&#xff1f;口令&#xff01;"了。我們需要的是一套像FBI一樣具備全方位偵察能力的智能防護系統。 &#x1f4cb; 文章目錄 1. 什么是EDR/XDR&#xff1f;別被這…

Stream流-Java

Stream流的作用&#xff1a;結合了Lambda表達式&#xff0c;簡化集合&#xff0c;數組的操作Stream流的使用步驟&#xff1a;1. 先得到一條Stream流&#xff08;流水線&#xff09;&#xff0c;并把數據放上去獲取方式方法名說明單列集合default Stream<E> stream()Colle…

Leetcode 327. 區間和的個數

1.題目基本信息 1.1.題目描述 給你一個整數數組 nums 以及兩個整數 lower 和 upper 。求數組中&#xff0c;值位于范圍 [lower, upper] &#xff08;包含 lower 和 upper&#xff09;之內的 區間和的個數 。 區間和 S(i, j) 表示在 nums 中&#xff0c;位置從 i 到 j 的元素…

MinIO 版本管理實踐指南(附完整 Go 示例)

? 前言 在構建企業級對象存儲系統時,“對象的版本管理”是一個關鍵特性。MinIO 作為一款高性能、Kubernetes 原生的 S3 兼容對象存儲系統,也支持強大的版本控制功能。 本文將通過 Go 示例代碼 + 實操講解 的形式,手把手帶你掌握 MinIO 的版本控制能力,包括開啟版本控制、…

數組toString方法及類型檢測修復方案

在 JavaScript 中&#xff0c;數組的 toString() 方法被覆蓋&#xff08;重寫&#xff09;為返回數組元素的逗號分隔字符串&#xff0c;而不是原始的 [object Array] 類型標識。以下是詳細解釋和修復方案&#xff1a;問題原因Array.prototype.toString 被覆蓋數組繼承自 Object…