Why does this code output the error `fatal error: all goroutines are asleep - deadlock!`

48 views Asked by At

Recently I was learning go language and wrote a piece of code, but the output is wrongfatal error: all goroutines are asleep - deadlock!

I checked a lot of information on the Internet, but couldn't find the correct solution. Has anyone encountered this problem?

my environment is $ go version go1.17.8 darwin/arm64

m1 mac, system: macOS Monterey version 12.4 (21F79)

Code:

func main() {
    A := make(chan bool)
    B := make(chan bool)
    defer close(A)
    defer close(B)
    var wg sync.WaitGroup
    wg.Add(2)

    go func() {
        for i := 0; i < 10; i += 2 {
            if <-A {
                fmt.Println(i)
                B <- true
            }
        }
        wg.Done()
    }()

    go func() {
        for i := 1; i < 10; i += 2 {
            if <-B {
                fmt.Println(i)
                A <- true
            }
        }
        wg.Done()
    }()

    A <- true
    wg.Wait()
}
1

There are 1 answers

0
Kan Robert On

Looking at the code, it should be done with waitgroup, and two goroutine are executed alternately.

The problem lies in the last write of B routine to A <- true. At this time, the code that reads data from A channel has no chance to be executed. Add a simple read and it can be executed smoothly.

like it:

func main() {
    A := make(chan bool)
    B := make(chan bool)
    endch := make(chan struct{})
    defer close(A)
    defer close(B)
    defer close(endch)
    var wg sync.WaitGroup
    wg.Add(2)
    go func() {
        for i := 0; i < 10; i += 2 {
            if <-A {
                fmt.Println(i)
                B <- true
            }
        }
        wg.Done()

        endch <- struct{}{}
    }()

    go func() {
        for i := 1; i < 10; i += 2 {
            if <-B {
                fmt.Println(i)
                A <- true
            }
        }
        wg.Done()
    }()

    A <- true
    <-endch
    <-A
    wg.Wait()
}