Back
Featured image of post Go协程交替打印

Go协程交替打印

(1)用协程交替打印 ABC 一百次; (2)用协程交替打印数字,0 到 100。

我们可以利用 Channel 的阻塞机制来进行信号传递,因为无缓冲的 Channel 中,如果没有数据传入管道,那么该协程就会被阻塞。

问题一:打印 ABC

设计这样一个函数:参数一接收要打印的字母,参数二为 Channel 接收上一个协程传递的信息,参数三也为 Channel 负责给下一个协程传递发送信息,参数四为 sync.WaitGroup 确保线程能够执行完。

null
null

此外,这里需要注意的是,我们每个协程完成打印任务的时候就把 Channel 关闭,因此循环到打印 C 的线程时,ChanA 已经被关闭了,此时仍向它发送数据就会报错,所以要通过 recover 方法将异常捕获。

package main

import (
    "fmt"
    "sync"
)

func printABC(letter string, ch chan struct{}, nxtch chan struct{}, wg *sync.WaitGroup) {
    defer func() {
        wg.Done()  // 宣布协程完成任务
        close(ch)  // 关闭 channel
        if r := recover(); r != nil { //捕获异常
            fmt.Printf("\n")
        }
    }()

    for i := 0; i < 3; i++ {
        <-ch  // 接收信号并消费
        fmt.Print(letter)
        nxtch <- struct{}{}  // 发送信号给下个协程
    }
}

func main() {
    var wg sync.WaitGroup

    chA := make(chan struct{})
    chB := make(chan struct{})
    chC := make(chan struct{})

    wg.Add(3)
    go printABC("A", chA, chB, &wg)
    go printABC("B", chB, chC, &wg)
    go printABC("C", chC, chA, &wg)

    // START
    chA <- struct{}{}
    wg.Wait()
}

问题二:打印 0 到 100

函数的设计逻辑与问题一没有什么区别,主要就是在循环要打印的内容上做了一些更改,根据第一次初始化协程传入的参数开始循环打印。

null
null

package main  
  
import (  
    "fmt"  
    "sync")  
  
func printNum(start int, ch chan struct{}, nxtch chan struct{}, wg *sync.WaitGroup) {  
    defer func() {  
       wg.Done()                     // 宣布协程完成任务  
       close(ch)                     // 关闭 channel       if r := recover(); r != nil { //捕获异常  
          fmt.Printf("\n")  
       }  
    }()  
  
    for i := start; i <= 2; i += 2 {  
       <-ch // 接收信号并消费  
       fmt.Printf("%d ", i)  
       nxtch <- struct{}{} // 发送信号给下个协程  
    }  
}  
  
func main() {  
    var wg sync.WaitGroup  
  
    chA := make(chan struct{})  
    chB := make(chan struct{})  
  
    wg.Add(2)  
    go printNum(0, chA, chB, &wg)  
    go printNum(1, chB, chA, &wg)  
  
    // START  
    chA <- struct{}{}  
    wg.Wait()  
}
Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy
© Licensed Under CC BY-NC-SA 4.0