两个goroutine 循环打印1~10

jxy_90 · · 7485 次点击
应该还是比较好理解的写法 ```go package main import ( "fmt" "sync" ) func main() { i := 1 var wg sync.WaitGroup ch1, ch2, done := make(chan struct{}), make(chan struct{}), make(chan struct{}) wg.Add(2) job := func(accept, send chan struct{}) { label: for { select { //收到通知开始工作 case <-accept: fmt.Println(i) if i == 100 { //通知所有协程完成 close(done) } else { i++ //通知另一个开始工作 send <- struct{}{} } case <-done: break label } } wg.Done() } go job(ch1, ch2) go job(ch2, ch1) ch1 <- struct{}{} wg.Wait() //可以不做 close(ch1) close(ch2) } ```
#18
更多评论
现在定义上面的协程为 g1 现在定义下面的协程为 g2 你这段逻辑,不管怎么输出,其执行的顺序一定是 g1 g2 g2 g1 g1 g2 g2 g1 ... 按照这个线性逻辑,去和你的输出做匹配,你就会发现问题所在
#1
```golang 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 就是你打印的那部分 ```bash 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