使用带缓冲channel可实现信号量控制并发,容量设为最大并发数,goroutine通过发送和接收操作获取与释放信号量,确保最多3个任务同时执行。

在Go语言中,信号量常用于控制并发的goroutine数量,防止资源被过度占用。虽然Go标准库没有直接提供信号量类型,但可以通过 channel 和 sync 包模拟实现。下面介绍几种常见的控制并发数量的方案。
使用带缓冲的channel实现信号量
这是最常见、最简洁的方式。通过一个带缓冲的channel来充当信号量,容量即为最大并发数。
示例代码:
package mainimport ("fmt""sync""time")
const maxConcurrency = 3var sem = make(chan struct{}, maxConcurrency)
func worker(id int, wg *sync.WaitGroup) {defer wg.Done()
// 获取信号量(进入临界区)sem <- struct{}{}defer func() { <-sem }() // 释放信号量fmt.Printf("Worker %d 开始工作n", id)time.Sleep(2 * time.Second) // 模拟任务耗时fmt.Printf("Worker %d 完成n", id)
}
立即学习“go语言免费学习笔记(深入)”;
func main() {var wg sync.WaitGroup
for i := 1; i <= 10; i++ { wg.Add(1) go worker(i, &wg)}wg.Wait()
}
说明:channel容量为3,最多允许3个goroutine同时执行任务。其他goroutine会阻塞在
sem <- struct{}{}
直到有空位。
封装成可复用的信号量类型
为了更清晰地表达语义,可以封装一个简单的信号量结构。
type Semaphore struct { ch chan struct{}}func NewSemaphore(n int) *Semaphore {return &Semaphore{ch: make(chan struct{}, n)}}
func (s *Semaphore) Acquire() {s.ch <- struct{}{}}
func (s *Semaphore) Release() {<-s.ch}
使用方式与上面一致,但语义更清晰:
sem := NewSemaphore(3)sem.Acquire()defer sem.Release()
使用 sync.WaitGroup + channel 控制批量并发
适用于需要控制一批任务并发执行的场景,比如并发抓取网页、批量上传等。
urls := []string{"url1", "url2", ..., "url100"}sem := make(chan struct{}, 10) // 最多10个并发var wg sync.WaitGroupfor _, url := range urls {wg.Add(1)go func(u string) {defer wg.Done()sem <- struct{}{}defer func() { <-sem }()
fetch(u) // 执行任务}(url)
}
立即学习“go语言免费学习笔记(深入)”;
wg.Wait()
注意事项
使用空结构体
struct{}{}
作为信号量值,不占内存空间,最节省资源。确保每次 Acquire 后都有对应的 Release,建议配合 defer 使用。channel 容量即为最大并发数,设置要合理,避免过高导致资源耗尽,过低影响效率。该信号量不支持超时或抢占,如需更复杂控制可结合
context
实现。
基本上就这些。用channel实现信号量简单高效,是Go中控制并发数的惯用做法。
以上就是Golang信号量实现 控制并发数量方案的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1400694.html
微信扫一扫
支付宝扫一扫