dongzhuifeng1843 2016-09-30 22:03
浏览 307
已采纳

在先前的Wait返回之前,WaitGroup被重用

So im getting further into using golang and looking more into the concurrency it offers. I decided to try to use go routines to implement permutations of strings in a phone number.

I am running into issues using sync.WaitGroup to coordinate the go routines that i have been using. the specific error being:

WaitGroup is reused before previous Wait has returned

the code being:

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

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

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("
")
}

So after research that line is called during wg.Wait() or rathe wait groups wait function. 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. any insight into why this would be happening would be helpful

repo for refrence can be found at: https://github.com/sbiscigl/phonenumberperm

  • 写回答

1条回答 默认 最新

  • donglanfu5831 2016-09-30 22:09
    关注

    In your recursive cases in ThreadSafeCalcWords, you're calling wg.Done before calling 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. 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.

    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. 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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化