登录
首页 >  Golang >  Go问答

已使用 waitgroup 时切片的长度会有所不同

来源:stackoverflow

时间:2024-03-31 19:36:32 234浏览 收藏

本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《已使用 waitgroup 时切片的长度会有所不同》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~

问题内容

我很难理解并发/并行。在我的代码中,我做了一个 5 个循环的循环。在循环内部,我添加了 wg.add(1),总共有 5 个 add。代码如下:

package main

import (
    "fmt"
    "sync"
)

func main() {
    var list []int
    wg := sync.WaitGroup{}
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(c *[]int, i int) {
            *c = append(*c, i)
            wg.Done()
        }(&list, i)
    }
    wg.Wait()
    fmt.Println(len(list))
}

主函数会等待所有 goroutine 完成,但是当我尝试打印切片的长度时,我得到了随机结果。 ex (1,3,etc) 是否缺少一些东西才能得到预期的结果,即 5 ?


解决方案


是的,正确的同步。如果多个 goroutine 访问同一个变量,其中至少有一个是写入,则需要显式同步。

您的示例可以使用单个互斥锁来“保护”:

var list []int
wg := sync.WaitGroup{}

mu := &sync.Mutex{} // A mutex

for i := 0; i < 5; i++ {
    wg.Add(1)
    go func(c *[]int, i int) {
        mu.Lock() // Must lock before accessing shared resource
        *c = append(*c, i)
        mu.Unlock() // Unlock when we're done with it
        wg.Done()
    }(&list, i)
}
wg.Wait()

fmt.Println(len(list))

这将始终打印 5。

注意:在最后读取相同的切片以打印其长度,但我们没有在那里使用互斥锁。这是因为 waitgroup 的使用确保我们只能在修改它的所有 goroutine 完成其工作后才能到达该点,因此那里不会发生数据竞争。但一般来说,读和写都必须同步。

查看可能的重复项:

go routine not collecting all objects from channel

Server instances with multiple users

Why does this code cause data race?

How safe are Golang maps for concurrent Read/Write operations?

golang struct concurrent read and write without Lock is also running ok?

查看相关问题:

Can I concurrently write different slice elements

If I am using channels properly should I need to use mutexes?

Is it safe to read a function pointer concurrently without a lock?

Concurrent access to maps with 'range' in Go

理论要掌握,实操不能落!以上关于《已使用 waitgroup 时切片的长度会有所不同》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

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