问题:如何用两个协程交替打印ABAB?
锁
先尝试用锁,会发现不行,可能连续打印AA或BB,因为同一个协程里是循环, 可以释放锁后再获取锁。加上延迟时间也不行,都延迟等于都不延迟,至于延迟时间不同,那就更不行了,延迟短的会更快打印。
wg := sync.WaitGroup{}
wg.Add(2)
lk := sync.Mutex{}
go func() {
defer wg.Done()
for i := 0; i < 10; i++ {
lk.Lock()
fmt.Println("A")
lk.Unlock()
}
}()
go func() {
defer wg.Done()
for i := 0; i < 10; i++ {
lk.Lock()
fmt.Println("B")
lk.Unlock()
}
}()
wg.Wait()
一个channel
一个channel要好一点AB至少是成对的打印的,比如打印AB,BA;问题就是先AB再BA,那中间两个字母还是连续,要ABAB这样才行。原因应该是读取 channel 的数据顺序是顺序读取的,但是goroutine 运行顺序,由调度器调度的,io操作的时候 goroutine可能切换了。
func AlternatePrint() {
wg := sync.WaitGroup{}
c1 := make(chan int, 1)
wg.Add(2)
go func() {
defer wg.Done()
for i := 0; i < 10; i++ {
<-c1
fmt.Println("A")
}
}()
go func() {
defer wg.Done()
for i := 0; i < 10; i++ {
fmt.Println("B")
c1 <- 1
}
}()
c1 <- 1
wg.Wait()
}
2个协程
一个协程用来控制协程交替运行,一个协程用来控制打印交替。
func AlternatePrint() {
wg := sync.WaitGroup{}
c1 := make(chan string, 0)
c2 := make(chan string, 0)
wg.Add(2)
go func() {
defer wg.Done()
for i := 0; i < 10; i++ {
fmt.Println(<-c1, i)
c2 <- "B"
}
}()
go func() {
defer wg.Done()
for i := 0; i < 10; i++ {
c1 <- "A"
fmt.Println(<-c2, i)
}
}()
wg.Wait()
}