Go 如何正确使用通道来控制并发性?

Go 如何正确使用通道来控制并发性?,go,concurrency,Go,Concurrency,我对Go中的并发性还不熟悉,我正在尝试找出如何使用通道来控制并发性。我想做的是有一个循环,在这个循环中,我可以使用一个新的go例程调用一个函数,并在该函数处理时继续循环,我想将运行的例程数量限制为3个。我第一次尝试这样做的代码如下: func write(val int, ch chan bool) { fmt.Println("Processing:", val) time.Sleep(2 * time.Second) ch <- val % 3 == 0 }

我对Go中的并发性还不熟悉,我正在尝试找出如何使用通道来控制并发性。我想做的是有一个循环,在这个循环中,我可以使用一个新的go例程调用一个函数,并在该函数处理时继续循环,我想将运行的例程数量限制为3个。我第一次尝试这样做的代码如下:

func write(val int, ch chan bool) {
    fmt.Println("Processing:", val)
    time.Sleep(2 * time.Second)
    ch <- val % 3 == 0
}

func main() {
    ch := make(chan bool, 3) // limit to 3 routines?
    for i := 0; i< 10; i++ {
        go write(i, ch)
        resp := <- ch
        fmt.Println("Divisible by 3:", resp)
    }
    time.Sleep(20 * time.Second)
}
func写入(val int,ch chan bool){
fmt.Println(“处理:,val)
时间。睡眠(2*时间。秒)

ch这里的问题很简单:

for i := 0; i< 10; i++ {
    go write(i, ch)
    resp := <- ch
    fmt.Println("Divisible by 3:", resp)
}
i:=0;i<10;i++{ 去写(i,ch)
resp:=还有一种方法可以并行运行go例程,并等待所有例程返回通道上的值,即使用
等待组
。这也有助于同步go例程。如果您使用go例程等待所有例程完成,然后再执行另一个函数,更好的方法是使用
等待组

package main

import (
    "fmt"
    "time"
    "sync"
)

func write(val int, wg *sync.WaitGroup, ch chan bool) {
    defer wg.Done()
    fmt.Println("Processing:", val)
    time.Sleep(2 * time.Second)
    ch <- val % 3 == 0
}
func main() {
    wg := &sync.WaitGroup{}
    ch := make(chan bool, 3)
    for i := 0; i< 10; i++ {
        wg.Add(1)
        go write(i, wg, ch)
    }
    for i := 0; i< 10; i++ {
        fmt.Println("Divisible by 3: ", <-ch)
    }
    close(ch)
    wg.Wait()
    time.Sleep(20 * time.Second)
}
主程序包
进口(
“fmt”
“时间”
“同步”
)
func write(val int,wg*sync.WaitGroup,ch chan bool){
推迟工作组完成()
fmt.Println(“处理:,val)
时间。睡眠(2*时间。秒)

作为旁注,你真的需要在这里控制并发吗?Goroutines更像是线程池中的任务,而不是操作系统线程。当然,细节有点复杂,但是你可以在内核中发送几十个,而不需要几十个线程上下文切换的开销。仍然有很好的理由控制并发nWalk(例如,下载器可能不希望有1000个并发的输出连接…),但是如果你来自C++或C语言,它们并不像你想象的那么普通。
package main

import (
    "fmt"
    "time"
    "sync"
)

func write(val int, wg *sync.WaitGroup, ch chan bool) {
    defer wg.Done()
    fmt.Println("Processing:", val)
    time.Sleep(2 * time.Second)
    ch <- val % 3 == 0
}
func main() {
    wg := &sync.WaitGroup{}
    ch := make(chan bool, 3)
    for i := 0; i< 10; i++ {
        wg.Add(1)
        go write(i, wg, ch)
    }
    for i := 0; i< 10; i++ {
        fmt.Println("Divisible by 3: ", <-ch)
    }
    close(ch)
    wg.Wait()
    time.Sleep(20 * time.Second)
}