英文:
count / display the number of active goroutines
问题
我有一个队列和一个既可以出队又可以入队的函数。只要列表中有内容,我希望确保有适量的goroutine在队列上运行。
这是我正在使用的代码,但我想知道是否有一种方法可以打印当前活动的goroutine数量。
var element int
func deen(queue chan int) {
element := <-queue
fmt.Println("element is ", element)
if element%2 == 0 {
fmt.Println("new element is ", element)
queue <- (element*100 + 11)
queue <- (element*100 + 33)
}
}
func main() {
queue := make(chan int, 10)
queue <- 1
queue <- 2
queue <- 3
queue <- 0
for len(queue) != 0 {
for i := 0; i < 2; i++ {
go deen(queue)
}
}
fmt.Scanln()
fmt.Println("list is has len", len(queue)) //this must be 0
}
英文:
I have a queue and a function that does both dequeueing and enqueueing. I want to make sure that the right amount of goroutines operate on the queue, as long as there is something in the list.
This is the code I am using, but I was wondering if there is a way of printing the amount of currently active goroutines
var element int
func deen(queue chan int) {
element := <-queue
fmt.Println("element is ", element)
if element%2 == 0 {
fmt.Println("new element is ", element)
queue <- (element*100 + 11)
queue <- (element*100 + 33)
}
}
func main() {
queue := make(chan int, 10)
queue <- 1
queue <- 2
queue <- 3
queue <- 0
for len(queue) != 0 {
for i := 0; i < 2; i++ {
go deen(queue)
}
}
fmt.Scanln()
fmt.Println("list is has len", len(queue)) //this must be 0
}
答案1
得分: 25
这是一段关于使用Go语言中的sync.WaitGroup的代码示例。它解决了在循环中创建大量goroutine和浪费CPU周期的问题。
代码中定义了一个名为deen的函数,它接受一个sync.WaitGroup类型的指针和一个int类型的通道作为参数。在deen函数中,通过range循环从通道中读取元素,并对元素进行处理。如果元素是偶数,它会创建两个新的元素,并将它们发送到通道中。然后,通过调用wg.Done()来表示一个goroutine的工作已经完成。
在main函数中,首先创建了一个sync.WaitGroup类型的变量wg和一个容量为10的int类型通道queue。然后,将一些初始元素发送到通道中。接下来,使用for循环创建了4个goroutine,并将它们启动。每个goroutine都调用deen函数,并传递了wg和queue作为参数。最后,通过调用wg.Wait()等待所有的goroutine完成工作,然后关闭通道并打印队列的长度。
这段代码的目的是确保最后打印的队列长度为0,以验证所有的goroutine都已经完成工作。
你可以在这里找到完整的代码示例:playground。
另外,还提供了一个旧版本的代码,其中存在竞态条件。在这个版本中,wg.Done()的调用位置不正确,可能导致goroutine计数不正确。这个问题在新版本的代码中得到了修复。
你可以在这里找到旧版本的代码:playground。
英文:
There's runtime.NumGoroutine
but you're approaching this wrong.
- Your loops will keep spawning goroutines.
- this will unnecessarily burn cpu cycles because of the for loop.
One approach is to use a sync.WaitGroup.
func deen(wg *sync.WaitGroup, queue chan int) {
for element := range queue {
fmt.Println("element is ", element)
if element%2 == 0 {
fmt.Println("new element is ", element)
wg.Add(2)
queue <- (element*100 + 11)
queue <- (element*100 + 33)
}
wg.Done()
}
}
func main() {
var wg sync.WaitGroup
queue := make(chan int, 10)
queue <- 1
queue <- 2
queue <- 3
queue <- 0
for i := 0; i < 4; i++ {
wg.Add(1)
go deen(&wg, queue)
}
wg.Wait()
close(queue)
fmt.Println("list len", len(queue)) //this must be 0
}
--- old buggy version with a race in it ---
func deen(wg *sync.WaitGroup, queue chan int) {
for element := range queue {
wg.Done()
fmt.Println("element is ", element)
if element%2 == 0 {
fmt.Println("new element is ", element)
wg.Add(2)
queue <- (element*100 + 11)
queue <- (element*100 + 33)
}
}
}
func main() {
var wg sync.WaitGroup
queue := make(chan int, 10)
queue <- 1
queue <- 2
queue <- 3
queue <- 0
for i := 0; i < 4; i++ {
wg.Add(1)
go deen(&wg, queue)
}
wg.Wait()
close(queue)
fmt.Println("list is has len", len(queue)) //this must be 0
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论