今天面试遇到"两个goroutine 循环打印1~100"
思路是一个goroutine放数据,一个goroutine读数据,可是结果却是乱序的
```golang
func Test_0(t *testing.T) {
//fmt.Println("123")
c1 := make(chan int)
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
for i := 0; i < 10; i += 2 {
c1 <- 1
fmt.Print(i)
}
wg.Done()
}()
go func() {
for i := 1; i < 10; i += 2 {
<-c1
fmt.Print(i)
}
wg.Done()
}()
wg.Wait()
}
```
=== RUN Test_0
0132457689--- PASS: Test_0 (0.00s)
PASS
----------------------------分割线----------------------------------
之后看了晚上的解答,只是循环的时候从+2->++,奇怪?这样就没问题呢?
```golang
func Test_dongchedi(t *testing.T) {
//fmt.Println("123")
c1 := make(chan int)
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
for i := 1; i <= 10; i++ {
c1 <- 1
if i%2 == 1 {
fmt.Print(i)
}
}
wg.Done()
}()
go func() {
for i := 1; i <= 10; i++ {
<-c1
if i%2 == 0 {
fmt.Print(i)
}
}
wg.Done()
}()
//c1 <- 1
wg.Wait()
}
```
=== RUN Test_dongchedi
12345678910--- PASS: Test_0(0.00s)
PASS
```go
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
```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