题目
使用两个goroutine交替打印1-100之间的奇数和偶数, 输出时按照从小到大输出。
涉及知识点
- 无缓冲的channel只能保存一个数据,当往无缓冲的channel写入第2个数据的时候协程会被阻塞,直到channel中的第1个数据被取走,才会唤醒被阻塞的协程。
- 如果主协程执行完成,但是,子协程未执行完成,子协程被杀死,程序退出。所以,需要使用WaitGroup等待所有子协程执行完成后再退出。
方案一
仅仅把无缓冲的channel当成一把锁使用
wg := sync.WaitGroup{}
wg.Add(2)
ch := make(chan int)
go func() {
defer wg.Done()
// 如果channel中没有数据,<-ch阻塞,直到channel中有一个数据时,取出channel的数据并判断i的值是否是偶数,如果是偶数,则打印
for i := 1; i < 10; i += 1 {
<-ch
if i%2 == 0 {
fmt.Println(i)
}
}
}()
// 第一次循环时,channel为空,可以向channel写入数据,此时i=1,所以,可以打印出1
// 第二次循环时,channel不为空,所以 ch <- 0语句阻塞,直到channel内没有数据
go func() {
defer wg.Done()
for i := 1; i < 10; i += 1 {
ch <- 0
if i%2 == 1 {
fmt.Println(i)
}
}
}()
wg.Wait()
方案二
从channel取出数据并打印channel中的数据,方案二与方案一主要区别是输出的数据来源不同,方案一输出的值是i,方案二输出的值是从channel内取出的。把奇偶数全部今次放到channel中。
wg := sync.WaitGroup{}
wg.Add(2)
ch := make(chan int)
go func() {
defer wg.Done()
for i := 1; i < 10; i += 1 {
val, _ := <-ch
if val > 0 && val%2 == 0 {
fmt.Println(val)
}
}
}()
go func() {
defer wg.Done()
for i := 1; i < 10; i += 1 {
if i%2 == 1 {
fmt.Println(i)
}
ch <- i
}
}()
wg.Wait()