Golang 并發機制-3:通道(channels)機制詳解

并發編程是一種創建性能優化且響應迅速的軟件的強大方法。Golang(也稱為 Go)通過通道(channels)這一特性,能夠可靠且優雅地實現并發通信。本文將揭示通道的概念,解釋其在并發編程中的作用,并提供有關如何通過無緩沖通道和有緩沖通道發送或接收數據的見解。

介紹通道

在Go語言中,通道是一個基本的特性,它支持在gooutine(并發執行線程)之間進行安全和同步的通信。它們充當管道,通過它可以在程序之間傳遞數據,促進并發程序中的協調和同步。

通道是單向的,這意味著它們既可以用于發送數據(<- chan)也可以用于接收數據(chan <- )。這種單向性有助于在程序間實現清晰和可控的數據流。
在這里插入圖片描述

發送和接收數據

1. 非緩存通道

無緩沖通道是一種同時發送和接收數據的通道。當在無緩沖通道上發送值時,發送方將阻塞,直到有相應的接收方準備接收該數據。同樣,接收器將阻塞,直到有可用的數據接收。

下面是一個說明使用非緩沖通道的示例:

package mainimport ("fmt""time"
)func main() {ch := make(chan int) // Create an unbuffered channelgo func() {ch <- 42 // Send data into the channel}()// time.Sleep(time.Second) // Give the Goroutine time to executevalue := <-ch // Receive data from the channelfmt.Println("Received:", value)
}

在這個例子中,一個線程將值 42發送到未緩沖的通道 ch.主線程接收它,程序將阻塞,直到發送方和接收方都準備好。

2. 緩存通道

緩沖通道支持使用指定的緩沖區大小異步發送和接收數據。這意味著只要緩沖區未滿,就可以在不等待接收器的情況下向通道發送多個值。同樣,只要緩沖區不是空的,接收方可以從通道中讀取數據,而不需要等待發送方。

下面是一個使用緩沖通道的例子:

package mainimport "fmt"func main() {ch := make(chan string, 2) // Create a buffered channel with a capacity of 2ch <- "Hello" // Send data into the channelch <- "World"fmt.Println(<-ch) // Receive data from the channelfmt.Println(<-ch)
}

在本例中,我們創建了容量為2的緩沖通道ch。我們可以在不阻塞的情況下向通道發送兩個值,然后接收并打印這些值。當你希望解耦發送方和接收方時,緩沖通道非常有用,允許它們在緩沖區大小約束下獨立工作。

  • 同步通道

Go中的通道同步是一種技術,用于通過使用通道來協調和同步Goroutines(并發線程)的執行。通道促進了程序之間安全和有序的通信,允許它們在完成特定任務或準備好數據時相互發送信號。這種同步機制對于確保運行例程以受控和同步的方式執行至關重要。

下面是通道同步有用的一些常見場景:

  1. 等待Goroutines完成:你可以使用通道來等待一個或多個Goroutines在繼續主程序之前完成它們的任務。
  2. 協調并行任務:通道可用于協調并發執行任務的多個goroutine,確保它們以特定順序完成工作或在特定點同步。
  3. 收集結果:通道可用于收集和聚合來自多個goroutine的結果,然后在所有goroutine完成其工作后處理它們。

讓我們用例子來探索這些場景:

  • 等待goroute完成
package mainimport ("fmt""sync"
)func worker(id int, wg *sync.WaitGroup) {defer wg.Done()fmt.Printf("Worker %d is working\n", id)
}func main() {var wg sync.WaitGroupfor i := 1; i <= 3; i++ {wg.Add(1)go worker(i, &wg)}wg.Wait() // Wait for all workers to finishfmt.Println("All workers have finished.")
}

在這個例子中,我們有三個工作程序。我們使用“同步”。WaitGroup’,等待所有工人完成他們的工作,然后打印“所有工人都完成了”。

  • 協同并行任務
package mainimport ("fmt""sync"
)func main() {var wg sync.WaitGroupch := make(chan int)for i := 1; i <= 3; i++ {wg.Add(1)go func(id int) {defer wg.Done()fmt.Printf("Goroutine %d is working\n", id)ch <- id // Send a signal to the channel when done}(i)}// Wait for all Goroutines to signal completiongo func() {wg.Wait()close(ch) // Close the channel when all Goroutines are done}()for id := range ch {fmt.Printf("Received signal from Goroutine %d\n", id)}fmt.Println("All Goroutines have finished.")
}

在本例中,我們有三個執行工作并使用通道發出完成信號的goroutine。我們使用“同步”。WaitGroup '等待所有的Goroutine完成,并且一個單獨的Goroutine偵聽通道以知道每個Goroutine何時完成其工作。

  • 收集結果
package mainimport ("fmt""sync"
)func worker(id int, resultChan chan<- int, wg *sync.WaitGroup) {defer wg.Done()result := id * 2resultChan <- result // Send the result to the channel
}func main() {var wg sync.WaitGroupresultChan := make(chan int, 3)for i := 1; i <= 3; i++ {wg.Add(1)go worker(i, resultChan, &wg)}wg.Wait() // Wait for all workers to finishclose(resultChan) // Close the channel when all results are sentfor result := range resultChan {fmt.Printf("Received result: %d\n", result)}
}

在本例中,三個工作線程程序計算結果并將其發送到通道。主程序等待所有工作線程完成,關閉通道,然后從通道讀取和處理結果。

這些示例說明了如何使用通道同步來協調和同步Go中各種并發編程場景中的Go例程。通道為線程間安全有序的通信提供了強大的機制,使編寫行為可預測且可靠的并發程序變得更加容易。

Select 語句: 多路復用通道(Multiplexing Channels)

管理并發任務的關鍵工具之一是“select”語句。在本文中,我們將探討“select”語句在多路復用通道中的作用,這是一種使Go程序員能夠有效地同步和協調Go例程的技術。

當你有多個通過各種渠道進行通信的goroutine時,可能需要有效地協調它們的活動。“select”語句支持通過選擇首個可以處理的通道操作來實現這一點。

下面是一個簡單的例子,演示了在多路信道中使用“select”:

package mainimport ("fmt""time"
)func main() {ch1 := make(chan string)ch2 := make(chan string)go func() {time.Sleep(time.Second)ch1 <- "Message from Channel 1"}()go func() {time.Sleep(time.Millisecond * 500)ch2 <- "Message from Channel 2"}()select {case msg1 := <-ch1:fmt.Println(msg1)case msg2 := <-ch2:fmt.Println(msg2)}fmt.Println("Main function exits")
}

在本例中,我們有兩個在兩個不同通道上發送消息的goroutine, ch1 ch2 select語句選擇可用的首個通道操作,允許我們從 ch1 ch2接收和打印消息。然后,程序繼續執行main函數,演示使用“select”的通道復用功能。

  • select 帶缺省分支

‘ select ’語句還支持‘ default ’情況,當您想要處理沒有通道操作準備好的情況時,這很有用。這里有一個例子:

package mainimport ("fmt""time"
)func main() {ch := make(chan string)go func() {time.Sleep(time.Second * 2)ch <- "Message from Channel"}()select {case msg := <-ch:fmt.Println(msg)default:fmt.Println("No message received")}fmt.Println("Main function exits")
}

在本例中,我們有一個在通道‘ ch ’上發送消息的程序。然而,“select”語句包含一個“default”情況,用于處理在預期時間內沒有消息到達的情況。這允許在沒有任何通道操作就緒的情況下進行優雅的處理。

Go中的最佳實踐和模式:扇出、扇入和關閉通道

當談到編寫干凈高效的Go代碼時,有一些最佳實踐和模式可以顯著提高并發程序的質量和性能。在本文中,我們將探討兩個基本實踐:Fan-out, Fan-in(扇出、扇入)和關閉通道。這些模式是在Go應用程序中管理并發性和通信的強大工具。

在這里插入圖片描述
在這里插入圖片描述
  1. 扇出,扇入

Fan-out, Fan-in模式是一種并發設計模式,允許你跨多個goroutine分發工作,然后收集和合并結果。當處理可以并發處理然后進行聚合的任務時,此模式特別有用。

  • 扇出,扇入示例
package mainimport ("fmt""math/rand""sync""time"
)func worker(id int, input <-chan int, output chan<- int) {for number := range input {// Simulate some worktime.Sleep(time.Millisecond * time.Duration(rand.Intn(100)))output <- number * 2}
}func main() {rand.Seed(time.Now().UnixNano())input := make(chan int)output := make(chan int)const numWorkers = 3var wg sync.WaitGroup// Fan-out: Launch multiple workersfor i := 0; i < numWorkers; i++ {wg.Add(1)go func(id int) {defer wg.Done()worker(id, input, output)}(i)}// Fan-in: Collect resultsgo func() {wg.Wait()close(output)}()// Send data to workersgo func() {for i := 1; i <= 10; i++ {input <- i}close(input)}()// Receive and process resultsfor result := range output {fmt.Println("Result:", result)}
}

在本例中,我們創建了三個worker goroutine,它們執行一些模擬工作,然后將結果發送到輸出通道。主程序生成輸入數據,單獨的程序使用扇入模式收集和處理結果。

  1. 關閉通道

關閉通道是發送數據傳輸完成信號和防止程序無限阻塞的基本做法。當你不再打算通過通道發送數據時,關閉通道以避免死鎖是至關重要的。

package mainimport "fmt"func main() {dataChannel := make(chan int, 3)go func() {defer close(dataChannel) // Close the channel when donefor i := 1; i <= 3; i++ {dataChannel <- i}}()// Receive data from the channelfor num := range dataChannel {fmt.Println("Received:", num)}
}

在本例中,我們創建了一個容量為3的緩沖通道‘ dataChannel ’。在向通道發送三個值之后,我們使用‘ close ’函數關閉它。關閉任何接收器的通道信號,不再發送數據。這允許接收程序在處理完所有數據后優雅地退出。

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

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

相關文章

Unity開發游戲使用XLua的基礎

Unity使用Xlua的常用編碼方式&#xff0c;做一下記錄 1、C#調用lua 1、Lua解析器 private LuaEnv env new LuaEnv();//保持它的唯一性void Start(){env.DoString("print(你好lua)");//env.DoString("require(Main)"); 默認在resources文件夾下面//幫助…

筆記:使用ST-LINK燒錄STM32程序怎么樣最方便?

一般板子在插件上&#xff0c; 8腳 3.3V;9腳 CLK;10腳 DIO;4腳GND ST_Link 19腳 3.3V;9腳 CLK;7腳 DIO;20腳 GND 燒錄軟件&#xff1a;ST-LINK Utility&#xff0c;Keil_5; ST_Link 接口針腳定義&#xff1a; 按定義連接ST_Link與電路板&#xff1b; 打開STM32 ST-LINK Uti…

網絡測試工具

工具介紹&#xff1a; 這是一個功能完整的網絡測速工具&#xff0c;可以測試網絡的下載速度、上傳速度和延遲。 功能特點&#xff1a; 1. 速度測試 - 下載速度測試 - 上傳速度測試 - Ping延遲測試 - 自動選擇最佳服務器 2. 實時顯示 - 進度條顯示測試進度 - 實時顯示測試狀…

java每日精進1.31(SpringSecurity)

在所有的開發的系統中&#xff0c;都必須做認證(authentication)和授權(authorization)&#xff0c;以保證系統的安全性。 一、基礎使用 1.依賴 <dependencies><!-- 實現對 Spring MVC 的自動化配置 --><dependency><groupId>org.springframework.bo…

簡單的SQL語句的快速復習

語法的執行順序 select 4 字段列表 from 1 表名列表 where 2 條件列表 group by 3 分組前過濾 having 分組后過濾 order by 5 排序字段列表 limit 6 分頁參數 聚合函數 count 統計數量 max 最大值 min 最小值 avg 平均 sum 總和 分組查詢使…

《程序人生》工作2年感悟

一些雜七雜八的感悟&#xff1a; 1.把事做好比什么都重要&#xff0c; 先樹立量良好的形象&#xff0c;再橫向發展。 2.職場就是人情世故&#xff0c;但也不要被人情世故綁架。 3.要常懷感恩的心&#xff0c;要記住幫助過你的人&#xff0c;愿意和你分享的人&#xff0c;有能力…

17.2 圖形繪制8

版權聲明&#xff1a;本文為博主原創文章&#xff0c;轉載請在顯著位置標明本文出處以及作者網名&#xff0c;未經作者允許不得用于商業目的。 17.2.10 重繪 先看以下例子&#xff1a; 【例 17.28】【項目&#xff1a;code17-028】繪制填充矩形。 private void button1_Clic…

自定義數據集 使用pytorch框架實現邏輯回歸并保存模型,然后保存模型后再加載模型進行預測,對預測結果計算精確度和召回率及F1分數

import numpy as np import torch import torch.nn as nn import torch.optim as optim from sklearn.metrics import precision_score, recall_score, f1_score# 數據準備 class1_points np.array([[1.9, 1.2],[1.5, 2.1],[1.9, 0.5],[1.5, 0.9],[0.9, 1.2],[1.1, 1.7],[1.4,…

neo4j入門

文章目錄 neo4j版本說明部署安裝Mac部署docker部署 neo4j web工具使用數據結構圖數據庫VS關系數據庫 neo4j neo4j官網Neo4j是用ava實現的開源NoSQL圖數據庫。Neo4作為圖數據庫中的代表產品&#xff0c;已經在眾多的行業項目中進行了應用&#xff0c;如&#xff1a;網絡管理&am…

腳本運行禁止:npm 無法加載文件,因為在此系統上禁止運行腳本

問題與處理策略 1、問題描述 npm install -D tailwindcss執行上述指令&#xff0c;報如下錯誤 npm : 無法加載文件 D:\nodejs\npm.ps1&#xff0c;因為在此系統上禁止運行腳本。 有關詳細信息&#xff0c;請參閱 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_…

Java基礎——分層解耦——IOC和DI入門

目錄 三層架構 Controller Service Dao ?編輯 調用過程 面向接口編程 分層解耦 耦合 內聚 軟件設計原則 控制反轉 依賴注入 Bean對象 如何將類產生的對象交給IOC容器管理&#xff1f; 容器怎樣才能提供依賴的bean對象呢&#xff1f; 三層架構 Controller 控制…

智慧園區系統集成解決方案引領未來城市管理的智能化轉型

內容概要 在現代城市管理的背景下&#xff0c;“智慧園區系統集成解決方案”正扮演著越來越重要的角色。這種解決方案不僅僅是技術上的創新&#xff0c;更是一種全新的管理理念&#xff0c;它旨在通過高效的數據整合與分析&#xff0c;優化資源配置&#xff0c;提升運營效率。…

99.24 金融難點通俗解釋:MLF(中期借貸便利)vs LPR(貸款市場報價利率)

目錄 0. 承前1. 什么是MLF&#xff1f;1.1 專業解釋1.2 通俗解釋1.3 MLF的三個關鍵點&#xff1a; 2. 什么是LPR&#xff1f;2.1 專業解釋2.2 通俗解釋2.3 LPR的三個關鍵點&#xff1a; 3. MLF和LPR的關系4. 傳導機制4.1 第一步&#xff1a;央行調整MLF4.2 第二步&#xff1a;銀…

【VM】VirtualBox安裝CentOS8虛擬機

閱讀本文前&#xff0c;請先根據 VirtualBox軟件安裝教程 安裝VirtualBox虛擬機軟件。 1. 下載centos8系統iso鏡像 可以去兩個地方下載&#xff0c;推薦跟隨本文的操作用阿里云的鏡像 centos官網&#xff1a;https://www.centos.org/download/阿里云鏡像&#xff1a;http://…

Elasticsearch中的度量聚合:深度解析與實戰應用

在大數據和實時分析日益重要的今天&#xff0c;Elasticsearch以其強大的搜索和聚合能力&#xff0c;成為了眾多企業和開發者進行數據分析和處理的首選工具。本文將深入探討Elasticsearch中的度量聚合&#xff08;Metric Aggregations&#xff09;&#xff0c;展示其如何在數據分…

C_C++輸入輸出(下)

C_C輸入輸出&#xff08;下&#xff09; 用兩次循環的問題&#xff1a; 1.一次循環決定打印幾行&#xff0c;一次循環決定打印幾項 cin是>> cout是<< 字典序是根據字符在字母表中的順序來比較和排列字符串的&#xff08;字典序的大小就是字符串的大小&#xff09;…

電腦要使用cuda需要進行什么配置

在電腦上使用CUDA&#xff08;NVIDIA的并行計算平臺和API&#xff09;&#xff0c;需要進行以下配置和準備&#xff1a; 1. 檢查NVIDIA顯卡支持 確保你的電腦擁有支持CUDA的NVIDIA顯卡。 可以在NVIDIA官方CUDA支持顯卡列表中查看顯卡型號是否支持CUDA。 2. 安裝NVIDIA顯卡驅動…

深入解析:一個簡單的浮動布局 HTML 示例

深入解析&#xff1a;一個簡單的浮動布局 HTML 示例 示例代碼解析代碼結構分析1. HTML 結構2. CSS 樣式 核心功能解析1. 浮動布局&#xff08;Float&#xff09;2. 清除浮動&#xff08;Clear&#xff09;3. 其他樣式 效果展示代碼優化與擴展總結 在網頁設計中&#xff0c;浮動…

家居EDI:Hom Furniture EDI需求分析

HOM Furniture 是一家成立于1977年的美國家具零售商&#xff0c;總部位于明尼蘇達州。公司致力于提供高品質、時尚的家具和家居用品&#xff0c;滿足各種家庭和辦公需求。HOM Furniture 以廣泛的產品線和優質的客戶服務在市場上贏得了良好的口碑。公司經營的產品包括臥室、客廳…

【VUE案例練習】前端vue2+element-ui,后端nodo+express實現‘‘文件上傳/刪除‘‘功能

近期在做跟畢業設計相關的數據后臺管理系統&#xff0c;其中的列表項展示有圖片展示&#xff0c;添加/編輯功能有文件上傳。 “文件上傳/刪除”也是我們平時開發會遇到的一個功能&#xff0c;這里分享個人的實現過程&#xff0c;與大家交流談論~ 一、準備工作 本次案例使用的…