为什么我需要睡两次才能看到 goroutines?

我用 go 编写了这个小程序。关于go关键字,我只知道当我以这种方式调用一个函数时,是同时执行的。我尝试在没有 time.Sleep() 的情况下执行此代码,但没有生成输出。我需要添加 time.Sleep(1000) 两次。一次。睡眠声明是不够的。为什么?


package main


import (

    "fmt"

    "time"

)


func doSomething(integer int) {

    fmt.Println(integer)

}


func main() {

    i := 1


    for i <= 10 {

        go doSomething(i)

        i++

    }


    time.Sleep(1000)

    time.Sleep(1000)

}


catspeake
浏览 214回答 2
2回答

www说

这是因为当您使用go(即作为 goroutine)调用函数时,它会在后台运行并继续执行。在这种情况下,在调用 goroutine 后,程序没有任何事情可做,所以它只是完成并且您看不到任何输出。为什么需要两个?好吧,您没有,只是 1 秒的睡眠时间不够长,如果您有,time.Sleep(2000)您可能会得到相同的结果(尽管不能保证)。通常,在使用 goroutine 时,您需要在某些地方使用某种阻塞语句。imo,最简单的方法是将通道传递给 goroutine,然后从它接收。由于代码的结构,这不是最有用的示例,但这是您的程序的修改版本,它将阻塞直到第一个 goroutine 完成。由于您实际上调用了 10 个 goroutine,因此您需要更强大的逻辑来阻止它们,直到它们完成,但更合理的解决方案是将循环放入 gouroutine,而不是调用 10 个 goroutine。https://play.golang.org/p/66g9u8Bhjj另外,请在 go tour 中查看这个更真实的示例;https://tour.golang.org/concurrency/2

蝴蝶不菲

试试这个:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "runtime"&nbsp; &nbsp; "time")func doSomething(integer int) {&nbsp; &nbsp; fmt.Println(integer)}func main() {&nbsp; &nbsp; i := 1&nbsp; &nbsp; for i <= 10 {&nbsp; &nbsp; &nbsp; &nbsp; go doSomething(i)&nbsp; &nbsp; &nbsp; &nbsp; i++&nbsp; &nbsp; }&nbsp; &nbsp; runtime.Gosched()&nbsp; &nbsp; time.Sleep(10 * time.Millisecond)}它会以不同的方式运行。你知道完成这个(你的)代码需要多少时间:(考虑 CPU 负载 100%,其他进程具有更高的优先级。)func doSomething(integer int) {&nbsp; &nbsp; fmt.Println(integer)}for i <= 10 {&nbsp; &nbsp; go doSomething(i)&nbsp; &nbsp; i++}简单的回答:没有。它取决于每个系统上的许多未知因素:1- CPU 速度和 CPU 内核和 CPU 缓存的数量...2- RAM 速度和总线速度以及总线矩阵(是否并发?)2- 操作系统调度程序和操作系统负载和优先级3- Golang 调度程序4- CPU 负载...我的意思是:在并发系统和并发编程中,依赖简单的代码(或汇编)指令时序并不是一个好主意。是的,了解 Golang 调度器及其工作原理是件好事,但是即使你知道 Golang 调度器的行为方式,你知道操作系统现在在做什么吗?仅在实时操作系统中,它估计为毫秒左右范围内的某个已知时间。甚至有时最好限制并发:这是限制并发的一种方法://using chan to limit the concurrencypackage mainimport (&nbsp; &nbsp; "os/exec"&nbsp; &nbsp; "runtime"&nbsp; &nbsp; "sync")func main() {&nbsp; &nbsp; numberOfJobs := 10&nbsp; &nbsp; c := make(chan *exec.Cmd, numberOfJobs)&nbsp; &nbsp; for i := 0; i < numberOfJobs; i++ {&nbsp; &nbsp; &nbsp; &nbsp; c <- exec.Command("notepad")&nbsp; &nbsp; }&nbsp; &nbsp; close(c)&nbsp; &nbsp; nCPU := runtime.NumCPU()&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; for i := 0; i < nCPU; i++ {&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for cmd := range c {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cmd.Run()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; }()&nbsp; &nbsp; }&nbsp; &nbsp; wg.Wait()}这是限制并发的另一种方法://using chan to limit the concurrencypackage mainimport (&nbsp; &nbsp; "os/exec"&nbsp; &nbsp; "runtime"&nbsp; &nbsp; "sync")func main() {&nbsp; &nbsp; n := runtime.NumCPU()&nbsp; &nbsp; dummy := make(chan bool, n)&nbsp; &nbsp; numberOfJobs := 10&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; for i := 0; i < numberOfJobs; i++ {&nbsp; &nbsp; &nbsp; &nbsp; cmd := exec.Command("notepad")&nbsp; &nbsp; &nbsp; &nbsp; dummy <- true // wait here if no CPU available&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go func(cmd *exec.Cmd) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //defer func() { <-dummy }()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cmd.Run()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <-dummy&nbsp; &nbsp; &nbsp; &nbsp; }(cmd)&nbsp; &nbsp; }&nbsp; &nbsp; close(dummy)&nbsp; &nbsp; wg.Wait()}我希望这有帮助。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go