Как на самом деле работает syn c .WaitGroup.Done ()? - PullRequest
0 голосов
/ 10 июля 2020

Я запустил приведенный ниже код для программы, которая создает 4 горутины, и, согласно полученному мной выводу, кажется, что мой код работает правильно, но выдает ошибку: - fatal error: all goroutines are asleep - deadlock!

Я добавил 4 WaitGroups и как каждая из горутин завершена, я выполнил wg.Done (), но до сих пор не понимаю, почему такая ошибка вообще должна возникать.

Мой код:

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

func sort(x []int) {

    fmt.Println("Initial: ", x)

    var i int
    var j int
    for i = 0; i < len(x); i++ {
        for j = 0; j < len(x)-i-1; j++ {
            if x[j] > x[j+1] {
                temp := x[j+1]
                x[j+1] = x[j]
                x[j] = temp
            }
        }
    }

    fmt.Println("Sorted: ", x)

    wg.Done()

}

func main() {

    fmt.Println("Enter an array of number preferrably in multiples of 4:- ")
    inputSlice := make([]int, 0, 1)

    for true {
        var n int
        fmt.Print("Enter the number: ")
        fmt.Scan(&n)

        inputSlice = append(inputSlice, n)
        fmt.Print("Do you want to continue adding numbers (y/n) ? ")
        var char string
        fmt.Scan(&char)

        if char == "n" || char == "N" {
            if len(inputSlice)%4 == 0 {
                break
            } else {
                fmt.Println("Please enter more ", 4-len(inputSlice)%4, " numbers")
            }
        }
        fmt.Println("Test: ", n)
        fmt.Println("Input: ", char)
    }

    fmt.Println("Initial: ", inputSlice)
    size := len(inputSlice)

    wg.Add(4)

    div := (size / 4)
    sort1 := inputSlice[:div]
    go sort(sort1)

    sort2 := inputSlice[div:(div * 2)]
    go sort(sort2)

    sort3 := inputSlice[(div * 2):(div * 3)]
    go sort(sort3)

    sort4 := inputSlice[(div * 3):]
    go sort(sort4)

    wg.Wait()

    final := make([]int, 0, 1)

    for _, val := range sort1 {
        final = append(final, val)
    }
    for _, val := range sort2 {
        final = append(final, val)
    }
    for _, val := range sort3 {
        final = append(final, val)
    }
    for _, val := range sort4 {
        final = append(final, val)
    }

    sort(final)

    fmt.Println("Sorted: ", final)

}

Мой вывод:

Enter an array of number preferrably in multiples of 4:- 
Enter the number: 1
Do you want to continue adding numbers (y/n) ? y
Test:  1
Input:  y
Enter the number: 2
Do you want to continue adding numbers (y/n) ? y
Test:  2
Input:  y
Enter the number: 3
Do you want to continue adding numbers (y/n) ? y
Test:  3
Input:  y
Enter the number: 4
Do you want to continue adding numbers (y/n) ? n
Initial:  [1 2 3 4]
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
        C:/Deepan/Text Books/NITK - Coursera/GoLang/Course3/week3.go:61 +0x658
exit status 2

Ответы [ 2 ]

1 голос
/ 10 июля 2020

Это всего 5 вызовов sort () , что означает 5 wg.Done () , однако вы добавили только wg.Add (4) . Это приводит к

panic: sync: negative WaitGroup counter
1 голос
/ 10 июля 2020

На самом деле у меня нет тупика, но есть другая ошибка: panic: sync: negative WaitGroup counter.

Вы добавляете 4 в группу ожидания:

wg.Add(4)

И вы вызываете wg.Done() в sort(), в 4 запущенных горутины. Это нормально.

Но у вас также есть "последний" sort() вызов в main:

sort(final)

И внутри wg.Done() также будет вызываться:

panic: sync: negative WaitGroup counter

«Простое» исправление - добавить его в группу ожидания перед вызовом sort:

wg.Add(1)
sort(final)
...