今天面试遇到"两个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
```
package main
import (
"fmt"
"sync"
)
const (
startNumber=1
endNumber=100
)
func main() {
var mu sync.Mutex
var wg sync.WaitGroup
number := startNumber
wg.Add(2)
go func() {
defer wg.Done()
for {
mu.Lock()
if number > endNumber {
mu.Unlock()
break
}
if number%2 == 0 {
fmt.Printf("goroutine 2 print %d \n", number)
number++
}
mu.Unlock()
}
}()
go func() {
defer wg.Done()
for {
mu.Lock()
if number > endNumber {
mu.Unlock()
break
}
if number%2 != 0 {
fmt.Printf("goroutine 1 print %d \n", number)
number++
}
mu.Unlock()
}
}()
wg.Wait()
}
```
#12
更多评论
现在定义上面的协程为 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