如何在不产生死锁的情况下拥有一个缓冲通道和多个读取器?

如何在不产生死锁的情况下拥有一个缓冲通道和多个读取器?

问题描述:

FATAL Error All go routines are asleep. Deadlock.

This is what I tried. I am calling wg.Done(). What is missing?

package main

import (
    "fmt"
    "strconv"
    "sync"
)

func sender(wg *sync.WaitGroup, cs chan int) {
    defer wg.Done()
    for i := 0; i < 2; i++ {
        fmt.Println(i)
        cs <- i
    }
}

func reciever(wg *sync.WaitGroup, cs chan int) {
    x, ok := <-cs
    for ok {
        fmt.Println("Retrieved" + strconv.Itoa(x))
        x, ok = <-cs
        if !ok {
            wg.Done()
            break
        }
    }
}

func main() {
    wg := &sync.WaitGroup{}
    cs := make(chan int, 1000)
    wg.Add(1)
    go sender(wg, cs)
    for i := 1; i < 30; i++ {
        wg.Add(1)
        go reciever(wg, cs)
    }
    wg.Wait()
    close(cs)
}

You should to close channel before wg.Wait.
All your receivers are waiting for data from channel. That's why you have deadlock.
You can close channel at defer statement of sender function.
Also you need to wg.Done() if the first attempt of receiving from channel was unsuccessful (because channel already closed)

http://play.golang.org/p/qdEIEfY-kl

There are couple of things:

  1. You need to close the channel once sender is completed.
  2. In receiver, range over channel
  3. Don't need to add 1 to wait group and call Done in sender

Please refer to http://play.golang.org/p/vz39RY6WA7