简体   繁体   English

在上一次Wait返回之前重新使用WaitGroup

[英]WaitGroup is reused before previous Wait has returned

So im getting further into using golang and looking more into the concurrency it offers. 因此,我将进一步使用golang并进一步了解它提供的并发性。 I decided to try to use go routines to implement permutations of strings in a phone number. 我决定尝试使用go例程来实现电话号码中字符串的排列。

I am running into issues using sync.WaitGroup to coordinate the go routines that i have been using. 我遇到了使用sync.WaitGroup来协调我一直在使用的go例程的问题。 the specific error being: 具体错误是:

WaitGroup is reused before previous Wait has returned

the code being: 代码是:

main.go main.go

package main

import (
    "fmt"
    "sync"

    "github.com/sbiscigl/phonenumberperm/intstack"
    "github.com/sbiscigl/phonenumberperm/permutations"
)

var wg sync.WaitGroup

func main() {
    num := []int{2, 7, 1, 4, 5, 5, 2}    
    stack := intstack.New(num)
    permutationChannel := make(chan string)
    wg.Add(1)
    go permutations.ThreadSafeCalcWords(stack, "", permutationChannel, &wg)
    wg.Wait()
    /*Then consume, but not implimented*/
}

permutations/perm.go 排列/ perm.go

package permutations

import (
    "fmt"
    "sync"

    "github.com/sbiscigl/phonenumberperm/intstack"
)

var letterMap = map[int][]string{
    2: []string{"a", "b", "c"},
    3: []string{"d", "e", "f"},
    4: []string{"g", "h", "i"},
    5: []string{"j", "k", "l"},
    6: []string{"m", "n", "o"},
    7: []string{"p", "q", "r", "s"},
    8: []string{"t", "u", "v"},
    9: []string{"w", "x", "y", "z"},
}

func ThreadSafeCalcWords(s intstack.IntStack, word string, ch chan<- string,
    wg *sync.WaitGroup) {
    if s.IsEmpty() {
        ch <- fmt.Sprint(word)
        wg.Done()
    } else {
        /*Check to see if the values are 1 or zero as they*/
        /*have no letters associated with them*/
        if s.Peek() == 1 || s.Peek() == 0 {
            wg.Done()
            s.Pop()
            wg.Add(1)
            go ThreadSafeCalcWords(s, word, ch, wg)
        } else {
            wg.Done()
            for _, letter := range letterMap[s.Pop()] {
                wg.Add(1)
                go ThreadSafeCalcWords(s, word+letter, ch, wg)
            }
        }
    }
}

intstack/intstack.go intstack / intstack.go

package intstack

import "fmt"

const (
    maxSize = 100
)

/*IntStack implimentaiton of a stack for integers*/
type IntStack struct {
    valueList []int
    maxSize   int
}

/*New returns bew instace of IntStack*/
func New(nums []int) IntStack {
    return IntStack{
        valueList: nums,
        maxSize:   maxSize,
    }
}

/*Pop pops the top value off the stack*/
func (s *IntStack) Pop() int {
    var val int
    if !s.IsEmpty() {
        val = s.valueList[0]
        s.valueList = s.valueList[1:]
    } else {
        fmt.Println("stack is empty")
    }
    return val
}

/*Peek returns top value*/
func (s IntStack) Peek() int {
    return s.valueList[0]
}

/*IsEmpty checks if the stack is empty*/
func (s IntStack) IsEmpty() bool {
    if len(s.valueList) > 0 {
        return false
    }
    return true
}

/*Print prints out the contents of the stack*/
func (s IntStack) Print() {
    for _, element := range s.valueList {
        fmt.Print(element)
    }
    fmt.Print("\n")
}

So after research that line is called during wg.Wait() or rathe wait groups wait function. 所以经过研究,在wg.Wait()或者等待组等待函数期间调用该行。 I tried to replicate with a smaller program, but could not. 我尝试用较小的程序复制,但不能。 My hypothesis is that once it reaches the the Wait() after it calls the the go routine, that we can no longer edit the wait group, but that sounds wrong. 我的假设是,一旦它在调用go例程后到达Wait(),我们就不能再编辑等待组,但这听起来是错误的。 any insight into why this would be happening would be helpful 任何有关为什么会发生这种情况的见解都会有所帮助

repo for refrence can be found at: https://github.com/sbiscigl/phonenumberperm 可以在以下网址找到repo for refrence: https//github.com/sbiscigl/phonenumberperm

In your recursive cases in ThreadSafeCalcWords , you're calling wg.Done before calling wg.Add . ThreadSafeCalcWords的递归情况下,在调用wg.Done 之前调用wg.Add That means that the wg can drop down to 0 (which will trigger the Wait to complete) before you actually finish all the work. 这意味着在你真正完成所有工作之前,wg可以下降到0(这将触发Wait完成)。 Calling Add again while the Wait is still in the process of resolving is what triggers the error, but more importantly, it probably just plain isn't what you want. Wait仍处于解析过程中再次调用Add是触发错误的原因,但更重要的是,它可能只是简单而不是你想要的。

Change the order of operations so that you always Add any new work before doing Done on the existing work, and the Wait won't trigger prematurely. 更改操作顺序,以便在Done现有工作之前始终Add任何新工作,并且不会过早触发Wait The simplest way to accomplish this would probably be a single call to wg.Done() at the bottom of the function, or a single defer at the top, and removing all the others. 做到这一点最简单的方法很可能是一个单一的通话wg.Done()的函数,或单一的底部defer在顶部,并删除所有其他人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM