两个goroutine 循环打印1~10

jxy_90 · 2022-03-07 20:33:33 · 7811 次点击
func Test_pingpang(t *testing.T) {
    const N = 100

    ping := make(chan int, 1)
    pang := make(chan int, 1)
    done := make(chan [0]int)
    pingpang := func(in <-chan int, out chan<- int) { // 根本不需要关心到底是+=1还是+=2
        for x := range in {
            t.Log(x)
            if x < N {
                out <- (x + 1)
                continue
            }
            close(done)
            break
        }
    }

    ping <- 0 // 发球
    // 也不需要关心多少goroutine,甚至ping/pang也可以不配对。以下是斗地主3打1
    go pingpang(ping, pang)
    go pingpang(pang, ping)
    go pingpang(ping, pang)
    go pingpang(ping, pang)

    <-done
    close(ping)
    close(pang)
}
#17
更多评论

现在定义上面的协程为 g1 现在定义下面的协程为 g2 你这段逻辑,不管怎么输出,其执行的顺序一定是 g1 g2 g2 g1 g1 g2 g2 g1 ... 按照这个线性逻辑,去和你的输出做匹配,你就会发现问题所在

#1
package main

import (
    "fmt"
    "sync"
)

func main() {
    //fmt.Println("123")
    c1 := make(chan int)
    wg := sync.WaitGroup{}
    wg.Add(2)
    go func() {
        for i := 0; i < 10; i += 2 {
            fmt.Println("go1 sending ")
            c1 <- 1
            fmt.Println("go1 sent # test")
        }
        wg.Done()
    }()
    go func() {
        for i := 0; i < 10; i += 2 {
            fmt.Println("go2 receiving ")
            <-c1
            fmt.Println("go2 received # test")
        }
        wg.Done()
    }()
    wg.Wait()
}

结果如下 带 # test 就是你打印的那部分

go2 receiving 
go1 sending 
go1 sent # test
go1 sending 
go2 received # test
go2 receiving 
go2 received # test
go2 receiving 
go1 sent # test
go1 sending 
go1 sent # test
go1 sending 
go2 received # test
go2 receiving 
go2 received # test
go2 receiving 
go1 sent # test
go1 sending 
go1 sent # test
go2 received # test

可以看到,一旦完成一次 channel 的通信后,如果当前 goroutine 还在占用 processor, 那么就会继续运行,直到下一次阻塞

#2