我在并发方面缺少什么?

Rod*_*igo 1 concurrency go goroutine

我有一个非常简单的脚本,它发出一个获取请求,然后对响应执行一些操作。我有两个版本,第一个版本使用 goroutine,另一个版本没有,我对这两个版本进行了基准测试,速度没有差异。这是我正在做的事情的一个简单版本:

普通版:

func main() {
    url := "http://finance.yahoo.com/q?s=aapl"

    for i := 0; i < 250; i++ {
        resp, err := http.Get(url)
        if err != nil {
            fmt.Println(err)
        }

        fmt.Println(resp.Status)
    }
}
Run Code Online (Sandbox Code Playgroud)

日常安排:

func main() {
    url := "http://finance.yahoo.com/q?s=aapl"

    for i := 0; i < 250; i++ {
        wg.Add(1)
        go run(url, &wg)
        wg.Wait()
    }
}

func run(url string, wg *sync.WaitGroup) {
    defer wg.Done()
    resp, err := http.Get(url)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println(resp.Status)
}
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,当我使用 go 例程时,程序的执行时间会更长。为了有效地理解并发性,我缺少什么概念?

eva*_*nal 5

wg.Wait()您的示例的主要问题是您在 for 循环内调用。这会导致执行阻塞,直到您wg.Done()run. 因此,执行不是并发的,它发生在 goroutine 中,但在启动 goroutine 之后i和开始之前会阻塞i+1。如果您将该语句放在循环之后,如下所示,那么您的代码将不会阻塞,直到循环之后(所有 goroutine 都已启动,有些可能已经完成)。

func main() {
    url := "http://finance.yahoo.com/q?s=aapl"

    for i := 0; i < 250; i++ {
        wg.Add(1)
        go run(url, &wg)
        // wg.Wait() don't wait here cause it serializes execution
    }
    wg.Wait() // wait here, now that all goroutines have been started
}
Run Code Online (Sandbox Code Playgroud)