Go Channel应用系列之控制协程数量

开发 前端
我们在for循环中虽然一直在不停的启用协程,但能够运行的协程数量不会超过10个。这样利用了通道的阻塞特定,不用加锁就能实现控制协程数量的目的。

大家好,我是渔夫子。

今天给大家介绍一下如何利用go中的缓冲channel来控制协程的数量。如下示例:

package main

import (
    "fmt"
    "sync/atomic"
)

func main() {
    sem := make(chan struct{}, 10)
    var count int32
    for {
       //time.Sleep(5*time.Millisecond)
       go func() {
          sem <- struct{}{}
          atomic.AddInt32(&count, 1)
          defer func() {
             <-sem
             atomic.AddInt32(&count, -1)
         }()

          fmt.Printf("count is :%d\n", count)
      }()
   }
    
}

在这个示例中,我们首先在for外层初始化了一个缓冲channel:sem,该channel可以存放10个元素。在for循环中我们不停的启动协程。在协程中我们尝试往sem中发送元素,如果发送成功,就运行后面的逻辑,如果发送不成功,即sem空间已经满了,就利用channel的堵塞特性,该协程在这里堵塞等待。最后等某个协程运行完毕后,从通道sem中输出一个元素,这样就腾出来一个空间,让堵塞的一个协程继续运行了。

这样,我们在for循环中虽然一直在不停的启用协程,但能够运行的协程数量不会超过10个。这样利用了通道的阻塞特定,不用加锁就能实现控制协程数量的目的。

应用示例

在之前我们推荐过一个爬虫的开源项目:Geziyor。这个项目中就使用了这种方式来控制并发请求的数量。我们看下源代码:首先,在初始化的地方,先根据并发个数来初始化了一个缓冲通道,示例代码看源码第109行

图片图片

然后,在Start函数中,循环启动每一个采集的任务。源代码中的106行Start函数,如下:

图片图片

然后,在源代码的第220行,则启动任务协程,在任务协程中首先通过acquireSem函数往通道中发送一个消息,如果发送不成功就堵塞在这里,直到其他协程通过releaseSem释放通道中的一个空间出来。如下:

图片图片

好了,今天缓冲通道的其中应用场景就分享到这里。

责任编辑:武晓燕 来源: Go学堂
相关推荐

2023-07-27 13:46:10

go开源项目

2024-07-01 08:44:42

Go语言协程

2016-10-28 17:39:47

phpgolangcoroutine

2021-05-21 08:21:57

Go语言基础技术

2018-12-04 14:00:41

协程编程模式PHP

2024-12-03 15:15:22

2020-12-27 10:15:44

Go语言channel管道

2024-06-27 07:56:49

2021-04-25 09:36:20

Go协程线程

2021-05-20 09:14:09

Kotlin协程挂起和恢复

2024-05-29 08:05:15

Go协程通信

2021-09-16 09:59:13

PythonJavaScript代码

2022-10-28 10:45:22

Go协程GoFrame

2022-09-12 06:35:00

C++协程协程状态

2021-08-04 16:19:55

AndroidKotin协程Coroutines

2024-08-27 09:46:39

Go协程效率

2023-03-09 09:06:13

ChanneGo开发

2023-11-17 11:36:59

协程纤程操作系统

2021-09-27 23:28:29

Go多协程并发

2021-02-19 06:56:33

架构协程应用
点赞
收藏

51CTO技术栈公众号