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

为什么我要睡两次才能看到goroutines?,go,concurrency,Go,Concurrency,我用围棋写了这个小程序。关于go关键字,我只知道当我以这种方式调用函数时,是同时执行的。我试图在没有时间的情况下执行此代码的内容。Sleep(),但没有生成任何输出。我需要增加时间。睡眠(1000)两次。一次。睡眠声明是不够的。为什么? package main import ( "fmt" "time" ) func doSomething(integer int) { fmt.Println(integer) } func main() { i := 1

我用围棋写了这个小程序。关于
go
关键字,我只知道当我以这种方式调用函数时,是同时执行的。我试图在没有时间的情况下执行此代码的内容。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)
}
主程序包
进口(
“fmt”
“时间”
)
func doSomething(整数int){
fmt.Println(整数)
}
func main(){
i:=1

对于i来说,这是因为当您使用
go
调用函数时(即作为goroutine)它在后台运行并继续执行。在这种情况下,在调用goroutine后,程序无需执行任何操作,因此它只是完成,并且看不到任何输出。为什么需要两个呢?你不需要,只是1秒的睡眠时间不够长,如果你有
时间。sleep(2000)
你可能会得到相同的结果(虽然不能保证)。通常在使用goroutine时,在某些地方需要某种阻塞语句。imo,最简单的方法是将通道传递给goroutine,然后从中接收

由于代码的结构,这不是最有用的示例,但这里有一个修改后的程序版本,它将阻塞直到第一个goroutine完成。因为您实际上调用了10个goroutine,所以您需要更健壮的逻辑来阻塞直到其中一个完成,但更合理的解决方案是将循环放入其中goroutine,而不是调用10个goroutine


另外,请在go tour中查看这个更现实的示例;

这是因为当您使用
go
调用函数时(即作为goroutine)它在后台运行并继续执行。在这种情况下,在调用goroutine后,程序无需执行任何操作,因此它只是完成,并且看不到任何输出。为什么需要两个呢?你不需要,只是1秒的睡眠时间不够长,如果你有
时间。sleep(2000)
你可能会得到相同的结果(虽然不能保证)。通常在使用goroutine时,在某些地方需要某种阻塞语句。imo,最简单的方法是将通道传递给goroutine,然后从中接收

由于代码的结构,这不是最有用的示例,但这里有一个修改后的程序版本,它将阻塞直到第一个goroutine完成。因为您实际上调用了10个goroutine,所以您需要更健壮的逻辑来阻塞直到其中一个完成,但更合理的解决方案是将循环放入其中goroutine,而不是调用10个goroutine

另外,请在go tour中查看这个更现实的示例;

尝试以下方法:

package main

import (
    "fmt"
    "runtime"
    "time"
)

func doSomething(integer int) {
    fmt.Println(integer)
}

func main() {
    i := 1

    for i <= 10 {
        go doSomething(i)
        i++
    }
    runtime.Gosched()
    time.Sleep(10 * time.Millisecond)
}
主程序包
进口(
“fmt”
“运行时”
“时间”
)
func doSomething(整数int){
fmt.Println(整数)
}
func main(){
i:=1
对于i请尝试以下方法:

package main

import (
    "fmt"
    "runtime"
    "time"
)

func doSomething(integer int) {
    fmt.Println(integer)
}

func main() {
    i := 1

    for i <= 10 {
        go doSomething(i)
        i++
    }
    runtime.Gosched()
    time.Sleep(10 * time.Millisecond)
}
主程序包
进口(
“fmt”
“运行时”
“时间”
)
func doSomething(整数int){
fmt.Println(整数)
}
func main(){
i:=1

对于我来说,这个问题本质上与你的问题相同。@johncarcenter只是在围棋场上运行他的示例。goroutines一开始就执行完毕,因为没有其他语句。实际上,如何运行并不重要。如果它是一个exe,你双击它,如果你打开它,窗口就会关闭一个命令提示符并调用exe,窗口将保持打开状态并移动到下一个提示符。因为正在安排goroutine并调用
fmt.Println(整数)
需要1微秒以上的时间。@sensorario:是的,但这取决于您自己协调,可以是频道,也可以是同步。WaitGroupPlease condier请先阅读一本书(这将是一个好的开始,请参阅列表)试一试事情是好的,但是做这件事的任何基础知识都是浪费时间——无论是你的还是我们的。这和你的问题基本上是一样的。“约翰卡彭特只是在GO运动场上运行他的例子。实际上,如何运行并不重要。如果它是一个exe,您双击它,窗口将关闭,如果您打开一个命令提示符并调用exe,窗口将保持打开状态,并移动到下一个提示符。因为计划goroutine并调用
fmt.Println(整数)
需要1微秒以上的时间。@sensorario:是的,但这取决于您自己协调,可以是频道,也可以是同步。WaitGroupPlease condier请先阅读一本书(这将是一个好的开始,请参阅列表)试探一下事情是好的,但是做任何关于这个问题的基础知识都是浪费时间——无论是你的还是我们的。时间。睡眠(10000)这还不够。但是程序没有等待10秒。@sensorario没有时间可以保证工作,这就是为什么你应该使用通道。goroutine应该告诉调用者它已经完成,而不是依赖巧合。@sensorario:
time.Sleep(10000)
是10微秒。使用时间包中定义的常量,
time.Sleep(10×Time.第二) @ Jang-CARPARTEN:不是一个很难回答的问题:“GO是一种开源编程语言……”J.J.卡彭特,考虑阅读——它解释了运行时如何实现GOOTONIN到M线程上的M×N调度.时间.睡眠(10000)这还不够。但是程序没有等待10秒。@sensorario没有时间可以保证工作,这就是为什么你应该使用通道。goroutine应该告诉调用者它已经完成,而不是依赖巧合。@sensorario:
time.Sleep(10000)
是10微秒。使用时间包中定义的常量,
time.Sleep(10×Time.第二) J.J.卡朋特:不是一个很难回答的问题:“GO是一种开源编程语言……”J.J.卡彭特,考虑阅读——它解释了HO。
//using chan to limit the concurrency
package main

import (
    "os/exec"
    "runtime"
    "sync"
)

func main() {
    numberOfJobs := 10
    c := make(chan *exec.Cmd, numberOfJobs)
    for i := 0; i < numberOfJobs; i++ {
        c <- exec.Command("notepad")
    }
    close(c)

    nCPU := runtime.NumCPU()
    var wg sync.WaitGroup
    for i := 0; i < nCPU; i++ {
        wg.Add(1)
        go func() {
            for cmd := range c {
                cmd.Run()
            }
            wg.Done()
        }()
    }

    wg.Wait()
}
//using chan to limit the concurrency
package main

import (
    "os/exec"
    "runtime"
    "sync"
)

func main() {
    n := runtime.NumCPU()
    dummy := make(chan bool, n)
    numberOfJobs := 10
    var wg sync.WaitGroup
    for i := 0; i < numberOfJobs; i++ {
        cmd := exec.Command("notepad")
        dummy <- true // wait here if no CPU available
        wg.Add(1)
        go func(cmd *exec.Cmd) {
            //defer func() { <-dummy }()
            cmd.Run()
            wg.Done()
            <-dummy
        }(cmd)
    }
    close(dummy)

    wg.Wait()
}