協程
goroutine 是輕量級線程,調度由 Go 運行時進行管理的。Go 語言的并發控制主要使用關鍵字 go 開啟協程 goroutine。Go 協程(Goroutine)之間通過信道(channel)進行通信,簡單的說就是多個協程之間通信的管道。信道可以防止多個協程訪問共享內存時發生資源爭搶的問題。語法格式:
// 普通函數創建 goroutinego 函數名(參數列表)//匿名函數創建 goroutinego func(參數列表){//函數體}(調用參數列表)
協程可以開啟多少個?是否有限制呢?
func testRoutine() {var wg sync.WaitGroupfor i := 0; i < math.MaxInt32; i++ {wg.Add(1)go func(i int) {defer wg.Done()fmt.Printf("并發數量:%d/n", i)time.Sleep(time.Second)}(i)}wg.Wait()}
以上代碼開啟了 math.MaxInt32個協程的并發,執行后可以看到結果直接 panic:“panic: too many concurrent operations on a single file or socket (max 1048575)”。整個并發操作超出了系統最大值。
控制協程數量
sync 同步機制
使用 sync.WaitGroup 啟動指定數量的協程 goroutine。
func testRoutine() {var wg = sync.WaitGroup{}taskCount := 5 // 指定并發數量for i := 0; i < taskCount; i++ {wg.Add(1)go func(i int) {fmt.Println("go func ", i)wg.Done()}(i)}wg.Wait()}
如果 taskcount 設置的很大超出了限制的,則其還是沒有控制到并發數量。可以優化下設計,類似池的設計思想,通過允許最大連接數控制量,當超出了數量就需要等待釋放,有空閑的連接的時候才可以繼續執行。
func testRoutine() {task_chan := make(chan bool, 3) //100 為 channel長度wg := sync.WaitGroup{}defer close(task_chan)for i := 0; i < math.MaxInt; i++ {wg.Add(1)fmt.Println("go func ", i)task_chan <- truego func() {<-task_chandefer wg.Done()}()}wg.Wait()}
- 創建緩沖區大小為 3 的 channel,在沒有被接收的情況下,至多發送 3 個消息則被阻塞。通過 channel 控制每次并發的數量。
- 開啟協程前,設置 task_chan <- true,若緩存區滿了則阻塞
- 協程任務執行完成后就釋放緩沖區
- 等待所有的并發都處理結束后則函數結束。其實可以不使用 sync.WaitGroup。因使用 channel 控制并發處理的任務數量可以不用使用等待并發處理結束。
-
Channel
+關注
關注
0文章
32瀏覽量
12448 -
線程
+關注
關注
0文章
510瀏覽量
20858 -
go語言
+關注
關注
1文章
159瀏覽量
9819
原文標題:使用 channel 控制并發數量
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
談談協程的那些事兒
使用channel控制協程數量
評論