go - 如何在单个程序中使用多个 sync.WaitGroup

标签 go concurrency

在我的 Go 程序中,我为每个部门启动了多个工作组。
我想在退出程序之前等待每个部门的工作人员完成

我不能使用单个 WaitGroups,因为在实际场景中,我可能必须结束任何特定部门并且只需要等待。

这是代码的简化版本,但它会出现一条消息

panic: runtime error: invalid memory address or nil pointer dereference


package main

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

var wgMap map[string]*sync.WaitGroup

func deptWorker(dName string, id int) {
    defer wgMap[dName].Done()
    fmt.Printf("Department %s : Worker %d starting\n", dName, id)
    time.Sleep(time.Second)
    fmt.Printf("Department %s :  Worker %d done\n", dName, id)
}

func department(dName string) {
    var wg sync.WaitGroup
    for i := 1; i <= 3; i++ {
        wg.Add(1)
        go deptWorker(dName, i)
    }
    wgMap[dName] = &wg
}

func main() {
    go department("medical")
    go department("electronics")

    wgMap["medical"].Wait()
    wgMap["electronics"].Wait()
}

最佳答案

两个修复零 panic 你只需要使用

var wgMap = map[string]*sync.WaitGroup{} 

它将初始化 map 。但是,在我看来,最好在这里创建一个新的抽象,我们将其命名为“WaitMap”。

可以这样实现:
package main

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

type WaitMapObject struct {
    wg map[string]int
    mu sync.Mutex
    cond sync.Cond
}

func WaitMap() *WaitMapObject {
    m := &WaitMapObject{}
    m.wg = make(map[string]int)
    m.cond.L = &m.mu
    return m
}

func (m *WaitMapObject) Wait(name string) {
    m.mu.Lock()
    for m.wg[name] != 0 {
        m.cond.Wait()
    }
    m.mu.Unlock()
}

func (m *WaitMapObject) Done(name string) {
    m.mu.Lock()
    no := m.wg[name] - 1
    if no < 0 {
        panic("")
    }
    m.wg[name] = no
    m.mu.Unlock()
    m.cond.Broadcast()
}

func (m *WaitMapObject) Add(name string, no int) {
    m.mu.Lock()
    m.wg[name] = m.wg[name] + no
    m.mu.Unlock()
}

func deptWorker(dName string, id int, wm *WaitMapObject) {
    defer wm.Done(dName)
    fmt.Printf("Department %s : Worker %d starting\n", dName, id)
    time.Sleep(time.Second)
    fmt.Printf("Department %s :  Worker %d done\n", dName, id)
}

func department(dName string, wm *WaitMapObject) {
    for i := 1; i <= 3; i++ {
        wm.Add(dName,1)
        go deptWorker(dName, i, wm)
    }
    wm.Done(dName)
}

func main() {
    wm := WaitMap()

    wm.Add("mediacal",1)
    go department("medical", wm)

    wm.Add("electronics",1)
    go department("electronics", wm)

    wm.Wait("medical")
    wm.Wait("electronics")
}

关于go - 如何在单个程序中使用多个 sync.WaitGroup,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60137755/

相关文章:

unix - 当读取器断开连接时,命名管道 (FIFO) 数据会去哪里?

go - 反射(reflect)接口(interface)列表

pointers - go - 写入接口(interface)的函数{}

Node.js 并行运行两个函数

multithreading - get_multi/set_multi 原子?

go - golang的hystrix库“电路断开”而没有“超时”错误

go - 组织我的代码的惯用方式

go - time.NewTimer 没有按我的预期工作

c# - 互斥存储过程

java - 声明两个字段 volatile 就足够了吗?