все горутины спят - тупик! с группой ожидания - PullRequest
0 голосов
/ 24 января 2019

Это мой код, где я ошибся?

func main() {
  intChan := make(chan int)
  wg := sync.WaitGroup{}

  for i := 0;i<5;i++{
    wg.Add(1)
    go send(intChan,i,&wg)
  }

  wg.Add(1)
  go get(intChan,&wg)
  wg.Wait()
  time.Sleep(5*time.Second)
  close(intChan)
}

func send(c chan int,index int,wg *sync.WaitGroup){
  defer func() {
    wg.Done()
  }()

  c <- index
}

func get(c chan int,wg *sync.WaitGroup){
  defer func() {
    wg.Done()
  }()

  for i := range c{
    fmt.Printf("%d\n",i)
  }
}

Когда я запускаю это, я получаю ошибку fatal error: all goroutines are asleep - deadlock!

Вот информация об ошибке:

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc0000120d8)
    C:/Go/src/runtime/sema.go:56 +0x40
sync.(*WaitGroup).Wait(0xc0000120d0)
    C:/Go/src/sync/waitgroup.go:130 +0x6b
main.main()
    F:/go/src/demo/channel.go:94 +0xf9

goroutine 10 [chan receive]:
main.get(0xc00001c120, 0xc0000120d0)
    F:/go/src/demo/channel.go:112 +0xe0
created by main.main
    F:/go/src/demo/channel.go:92 +0xeb

спасибо за все, это мой первый вопрос.

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Как сказал Энди в комментариях, вы выйдете из функции get только тогда, когда все входные данные получены и канал закрыт. Как вы знаете, нужно получить пять вещей, в цикле которых может быть похожий цикл for:

func main() {
    intChan := make(chan int)
    wg := sync.WaitGroup{}

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go send(intChan, i, &wg)
    }

    wg.Add(1)
    go get(intChan, &wg)
    wg.Wait()
    close(intChan)
}

func send(c chan int, index int, wg *sync.WaitGroup) {
    defer func() {
        wg.Done()
    }()

    c <- index
}

func get(c chan int, wg *sync.WaitGroup) {
    defer func() {
        wg.Done()
    }()

    for i := 0; i < 5; i++ {
        input := <- c
        fmt.Printf("%d\n", input)
    }
}

https://play.golang.org/p/CB8HUKPBu2I

Если вы хотите придерживаться диапазона по каналу, вам придется закрыть его после отправки всех сообщений, что я и сделал бы, добавив вторую группу ожидания:

func main() {
    intChan := make(chan int)
    allSent := sync.WaitGroup{}

    for i := 0; i < 5; i++ {
        allSent.Add(1)
        go send(intChan, i, &allSent)
    }

    allReceived := sync.WaitGroup{}
    allReceived.Add(1)
    go get(intChan, &allReceived)

    allSent.Wait()
    close(intChan)
    allReceived.Wait()
}

func send(c chan int, index int, wg *sync.WaitGroup) {
    defer func() {
        wg.Done()
    }()

    c <- index
}

func get(c chan int, wg *sync.WaitGroup) {
    defer func() {
        wg.Done()
    }()

    for i := range c {
        fmt.Printf("%d\n", i)
    }
}

https://play.golang.org/p/svFVrBdwmAc

0 голосов
/ 24 января 2019

это может сработать!

func main() {
    intChan := make(chan int)
    wg := sync.WaitGroup{}

    for i := 0;i<5;i++{
        wg.Add(1)
        go send(intChan,i,&wg)
    }

    wg.Add(1)
    go get(intChan,&wg)

    wg.Wait()
    close(intChan)
}

func send(c chan int,index int,wg *sync.WaitGroup){
    defer func() {
        wg.Done()
    }()

    c <- index
}

func get(c chan int,wg *sync.WaitGroup){
    defer func() {
        wg.Done()
    }()

    for {
        select {
            case i := <-c:
                fmt.Printf("%d\n",i)
            default:
                return
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...