go协程-交替打印

207 阅读1分钟

问题:如何用两个协程交替打印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()
}