登录
首页 >  Golang >  Go问答

sync.Waitgroup 不会阻止执行

来源:stackoverflow

时间:2024-04-12 17:30:35 277浏览 收藏

偷偷努力,悄无声息地变强,然后惊艳所有人!哈哈,小伙伴们又来学习啦~今天我将给大家介绍《sync.Waitgroup 不会阻止执行》,这篇文章主要会讲到等等知识点,不知道大家对其都有多少了解,下面我们就一起来看一吧!当然,非常希望大家能多多评论,给出合理的建议,我们一起学习,一起进步!

问题内容

考虑这个代码片段

package main

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

func main() {
    wg := new(sync.waitgroup)
    nap := func() {
        wg.add(1)
        time.sleep(2 * time.second)
        fmt.println("nap done")
        wg.done()
    }

    go nap()
    go nap()
    go nap()

    fmt.println("nap time")
    wg.wait()
    fmt.println("all done")
}

运行这样的代码会给出预期的输出:

nap time
nap done
nap done
nap done
all done

现在让我们在 wg.wait() 之前省略第一个标准输出打印:

// fmt.println("nap time")
wg.wait()
fmt.println("all done")

输出现在变为意外:

all done

预期的位置:

nap done
nap done
nap done
all done

演示中的相同代码确实给出了此输出,而无需省略标准输出打印。

你能向我解释一下我缺少什么吗?


解决方案


尽管这看起来像魔术,但它有一个合乎逻辑的解释。 go 不保证 goroutine 的执行顺序。在给定的代码片段中生成了三个 goroutine,但实际上有四个:第一个是在执行开始时生成的。

省略标准输出打印

这个 goroutine 产生了三个午睡函数并继续其计划。它的速度非常快,以至于在任何生成的 goroutine 能够调用 wg.add(1) 之前,它就执行了 wg.wait()。结果wg.wait()没有阻塞执行,程序结束。

wg.wait() 之前打印到标准输出

在这种情况下,程序执行是不同的,goroutine 能够进行 wg.add(1) 调用,因为主 goroutine 不像第一种情况那么快。这种行为是无法保证的,这可以在链接的演示示例中看到。

与标准输出打印无关

以下代码示例将给出相同的预期输出:

time.sleep(time.second)
wg.wait()
fmt.println("all done")

fmt.println()time.sleep() 具有相同的影响。

惯用方式

规则很简单:在生成 goroutine 之前调用 wg.add(1)

package main

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

func main() {
    wg := new(sync.WaitGroup)
    nap := func() {
        time.Sleep(2 * time.Second)
        fmt.Println("nap done")
        wg.Done()
    }

    napCount := 3
    wg.Add(napCount)
    for i := 0; i < napCount; i++ {
        go nap()
    }

    wg.Wait()
    fmt.Println("all done")
}

今天关于《sync.Waitgroup 不会阻止执行》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>