协程顺序
直接使用3个Channel, 分别控制:
- f1和f2的先后关系.
- f2和f3的先后关系.
- f3和main的先后关系.
package main
import "fmt"
var c1 = make(chan struct{})
var c2 = make(chan struct{})
var c3 = make(chan struct{})
func f1() {
fmt.Println("first")
/* f1执行完毕,解除f2的阻塞 */
c1 <- struct{}{}
}
func f2() {
/* 等待f1 */
<-c1
fmt.Println("second")
/* f2执行完毕, 解除f3的阻塞 */
c2 <- struct{}{}
}
func f3() {
/* 等待f2 */
<-c2
fmt.Println("third")
/* f3执行完毕, 解除main的阻塞 */
c3 <- struct{}{}
}
func main() {
routineMap := map[int]func() {
1: f1,
2: f2,
3: f3,
}
for _, f := range routineMap {
go f()
}
defer close(c1)
defer close(c2)
defer close(c3)
<-c3
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
协程交替打印
https://leetcode.cn/problems/print-foobar-alternately/description/
实现方式非常简单, 使用两个Channel:
- 一个Channel容量是1, 里面里面有一个元素, 叫c1
- 一个Channel容量是0, 叫c2
对于需要交替执行的两个Part (Part1和Part2):
- Part1先从c1中拿到元素, 然后执行, 执行完一次后解除c2阻塞.
- Part2解除阻塞后执行, 执行完之后解除c1的阻塞.
- 然后循环.
package main
import (
"fmt"
"sync"
)
/* 创建两个Channel */
var c1 = make(chan struct{}, 1)
var c2 = make(chan struct{})
func main() {
/* 初始化c1有一个元素 */
c1 <- struct{}{}
/* 创建WaitGroup */
wg := sync.WaitGroup{}
wg.Add(2)
var n int
/* 从标准输入读入n */
fmt.Scanf("%d", &n)
/* 开启协程 */
go func() {
for i := 0; i < n; i ++ {
<-c1
fmt.Print("Foo")
c2 <- struct{}{}
}
wg.Done()
}()
go func() {
for i := 0; i < n; i ++ {
<-c2
fmt.Print("Bar")
c1 <- struct{}{}
}
wg.Done()
}()
/* 延迟关闭管道 */
defer close(c1)
defer close(c2)
wg.Wait()
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52