解题思路:
- 创建一个包含三个通道的通道队列
chanQueue
,用于协程之间的通信。 - 定义一个计数器变量
result
,用于跟踪当前打印的数字。 - 创建一个退出信号通道
exitChan
,用于通知主函数所有协程已完成任务。 - 初始化通道队列
chanQueue
,并将最后一个通道中的数据置为非零值,以启动第一个协程。 - 启动三个协程,每个协程负责打印数字和发送通道信号给下一个协程。
- 在每个协程中,使用无限循环来等待上一个协程的通道信号。
- 如果计数器变量
result
大于等于 10,说明已经打印完 1 到 10,发送退出信号到exitChan
。 - 在每个协程中打印当前数字并递增计数器变量
result
,然后发送通道信号给下一个协程。 - 主函数等待退出信号
exitChan
,确保所有协程都已完成任务。 - 打印 "done" 表示程序执行完成。
通过使用三个通道和协程之间的同步,每个协程在等待上一个协程的通道信号时,其他协程会被阻塞,从而实现了交替打印数字的效果。
sync.WaitGroup
用于等待三个 goroutine 完成任务,sync.Mutex
用于保护共享资源的并发访问。wg.Done()
和 mutex.Lock()
分别是对应方法的调用,用于减少计数器和获取互斥锁。
sync
包是 Go 语言提供的用于同步和并发控制的包。它提供了一些常用的同步原语,用于在多个 goroutine 之间进行协调和通信。
-
sync.WaitGroup
是一个计数器,用于等待一组 goroutine 完成任务。通过调用Add()
方法增加计数器的值,调用Done()
方法减少计数器的值,调用Wait()
方法阻塞直到计数器的值归零。 -
sync.Mutex
是一个互斥锁,用于保护共享资源的并发访问。通过调用Lock()
方法获取锁,调用Unlock()
方法释放锁,确保同一时间只有一个 goroutine 可以访问被保护的代码块。 -
wg.Done()
是一个WaitGroup
的方法,用于减少计数器的值。在每个 goroutine 完成任务后,调用Done()
方法通知WaitGroup
计数器减一。 -
mutex.Lock()
是一个互斥锁的方法,用于获取锁。在访问共享资源之前,调用Lock()
方法锁定互斥锁,确保只有一个 goroutine 可以访问被保护的代码块。文章来源:https://www.toymoban.com/news/detail-542013.html -
wg.Wait()
是一个WaitGroup
的方法,用于阻塞直到计数器的值归零。在调用Wait()
方法之后,程序会等待所有 goroutine 完成任务,然后才继续执行。文章来源地址https://www.toymoban.com/news/detail-542013.html
package main
import (
"fmt"
)
func main() {
chanNum := 3 // 定义通道数量为3
// 创建通道队列切片
chanQueue := make([]chan struct{}, chanNum)
var result = 0 // 定义计数器变量
exitChan := make(chan struct{}) // 创建退出信号通道
// 初始化通道队列
for i := 0; i < chanNum; i++ {
chanQueue[i] = make(chan struct{}) // 创建每个通道
if i == chanNum-1 {
go func(i int) {
chanQueue[i] <- struct{}{} // 启动最后一个协程,发送通道信号
}(i)
}
}
// 启动三个协程
for i := 0; i < chanNum; i++ {
var lastChan, curChan chan struct{}
if i == 0 {
lastChan = chanQueue[chanNum-1] // 获取上一个协程的通道
} else {
lastChan = chanQueue[i-1]
}
curChan = chanQueue[i] // 获取当前协程的通道
go func(i byte, lastChan, curChan chan struct{}) {
for {
<-lastChan // 等待上一个协程的通道信号
if result >= 10 {
exitChan <- struct{}{} // 如果已经打印完 1-10,则发送退出信号
return
}
result++
fmt.Println(result) // 打印数字
curChan <- struct{}{} // 发送通道信号给下一个协程
}
}('A'+byte(i), lastChan, curChan)
}
<-exitChan // 等待退出信号
fmt.Println("done") // 打印 "done"
}
到了这里,关于用3个go协程交替打印n到m的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!