66 multithreading go goroutine

TL; TR:请转到最后一部分告诉我你将如何解决这个问题.

我今天早上开始使用Golang来自Python.我想从Go调用一个闭源可执行文件几次,带有一点并发性,使用不同的命令行参数.我生成的代码工作正常,但我想得到你的输入以改进它.由于我处于早期学习阶段,我还将解释我的工作流程.

zenity

从Go调用可执行文件

所以,在Go中,我会这样:

package main
import "os/exec"
func main() {
    cmd := exec.Command("zenity", "--info", "--text='Hello World'")
    cmd.Run()
}
.Run().Start().Wait()

多次调用可执行文件

i
package main    
import (
    "os/exec"
    "strconv"
)

func main() {
    NumEl := 8 // Number of times the external program is called
    for i:=0; i<NumEl; i++ {
        cmd := exec.Command("zenity", "--info", "--text='Hello from iteration n." + strconv.Itoa(i) + "'")
        cmd.Run()
    }
}

好的,我们做到了!但我仍然看不到Go over Python的优势......这段代码实际上是以串行方式执行的.我有一个多核CPU,我想利用它.所以让我们用goroutines添加一些并发性.

Goroutines,或者让我的程序并行的方法

a)第一次尝试:到处添加"go"

go
package main
import (
    "os/exec"
    "strconv"
)

func main() {
    NumEl := 8 
    for i:=0; i<NumEl; i++ {
        go callProg(i)  // <--- There!
    }
}

func callProg(i int) {
    cmd := exec.Command("zenity", "--info", "--text='Hello from iteration n." + strconv.Itoa(i) + "'")
    cmd.Run()
}
time.Sleep
exec.Command

b)第二次尝试:使用goroutines池

sync.WaitGroup

其他一些资源建议使用缓冲通道来完成工作:

package main
import (
    "os/exec"
    "strconv"
)

func main() {
    NumEl := 8               // Number of times the external program is called
    NumCore := 4             // Number of available cores
    c := make(chan bool, NumCore - 1) 
    for i:=0; i<NumEl; i++ {
        go callProg(i, c)
        c <- true            // At the NumCoreth iteration, c is blocking   
    }
}

func callProg(i int, c chan bool) {
    defer func () {<- c}()
    cmd := exec.Command("zenity", "--info", "--text='Hello from iteration n." + strconv.Itoa(i) + "'")
    cmd.Run()
}
defer

c)第三次尝试:当所有孩子都死了之后死去

sync.WaitGroup
package main
import (
    "os/exec"
    "strconv"
    "sync"
)

func main() {
    NumEl := 8               // Number of times the external program is called
    NumCore := 4             // Number of available cores
    c := make(chan bool, NumCore - 1) 
    wg := new(sync.WaitGroup)
    wg.Add(NumEl)            // Set the number of goroutines to (0 + NumEl)
    for i:=0; i<NumEl; i++ {
        go callProg(i, c, wg)
        c <- true            // At the NumCoreth iteration, c is blocking   
    }
    wg.Wait() // Wait for all the children to die
    close(c)
}

func callProg(i int, c chan bool, wg *sync.WaitGroup) {
    defer func () {
        <- c
        wg.Done() // Decrease the number of alive goroutines
    }()
    cmd := exec.Command("zenity", "--info", "--text='Hello from iteration n." + strconv.Itoa(i) + "'")
    cmd.Run()
}

完成.

我的问题

  • 你知道任何其他正确的方法来限制一次执行的goroutines的数量吗?
exec.Command
  • 那段代码看起来不错吗?
  • 你知道在这种情况下如何避免使用虚拟通道吗?

我无法说服自己这样的虚拟通道是可行的.