今天面试遇到"两个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
我觉得这个方法更好!省去了数值奇偶判断逻辑。
但这里我有一个小疑问:第一个goroutine中的ch <- 1 和 <-ch会不会出现自己发送,同时自己又接收到刚刚发送的值?
for ; i <= 10; i += 2 {
fmt.Printf("curr_a: %d\n", i)
ch <- 1
<-ch
}
#7
更多评论
现在定义上面的协程为 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