2022-03-17 for循环条件中加入channel读取判定的问题

example:

package main

import (
    "fmt"
    "sync"
)

func main() {
    Test_0()
}

func Test_0() {
    //fmt.Println("123")
    c1 := make(chan bool, 1)
    c2 := make(chan bool, 1)
    c1 <- true
    wg := sync.WaitGroup{}
    wg.Add(2)
    go func() {
        for i := 0; <-c1 && i < 10; i += 2 {
            fmt.Printf("%v \n", i)
            c2 <- true
        }
        wg.Done()
    }()
    go func() {
        for i := 1; i < 10 && <-c2; i += 2 {
            fmt.Printf("%v\n", i)
            c1 <- true
        }
        wg.Done()
    }()
    wg.Wait()
}

运行结果:

B-LAJ9LVDL-1650:0316 dsong$ go run main02.go 
0 
1
2 
3
4 
5
6 
7
8 
9

如果修改两个for循环中的判断条件顺序:

go func() {
        for i := 0; i < 10 && <-c1; i += 2 {
            fmt.Printf("%v \n", i)
            c2 <- true
        }
        wg.Done()
    }()
    go func() {
        for i := 1; <-c2 && i < 10; i += 2 {
            fmt.Printf("%v\n", i)
            c1 <- true
        }
        wg.Done()
    }()

运行结果:

0 
1
2 
3
4 
5
6 
7
8 
9
fatal error: all goroutines are asleep - deadlock!

原因就是循环判定中读channel的顺序问题,由左到右,所以第二段代码的i=9时,执行c1 <-true,但是c1中i=10,跳出了循环,所以<-c2就陷入了deadlock导致报错。
可以加个close(c)

go func() {
        for i := 0; <-c1 && i < 3; i += 2 {
            fmt.Printf("%v \n", i)
            c2 <- true
        }
        wg.Done()
        close(c2)
    }()
    go func() {
        for i := 1; i < 3 && <-c2; i += 2 {
            fmt.Printf("%v\n", i)
            c1 <- true
        }
        wg.Done()
        close(c1)
    }()
    wg.Wait()

你可能感兴趣的:(2022-03-17 for循环条件中加入channel读取判定的问题)