今天面试遇到"两个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
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