面试题答案
一键面试1. 控制多个goroutine按顺序执行的实现方式
在Go语言中,可以通过Channel来控制多个goroutine按顺序执行。主要思路是利用Channel的阻塞特性,一个goroutine在完成任务后,通过Channel通知下一个goroutine开始执行。
2. 设计原理
- 阻塞与同步:Channel的发送和接收操作都是阻塞的。当一个goroutine尝试向一个已满的Channel发送数据,或者从一个空的Channel接收数据时,它会被阻塞,直到相应的操作可以继续。这种阻塞机制使得我们可以精确地控制goroutine的执行顺序。
- 信号传递:通过在Channel中传递数据(这里数据内容并不重要,重要的是传递这个动作),可以作为一种信号,通知其他goroutine可以开始执行。
3. 关键代码实现
以下是一个简单的示例代码,展示了如何使用Channel控制三个goroutine按顺序执行:
package main
import (
"fmt"
)
func main() {
// 创建两个Channel用于同步
var c1 = make(chan struct{})
var c2 = make(chan struct{})
// 第一个goroutine
go func() {
fmt.Println("goroutine 1 start")
// 模拟一些工作
fmt.Println("goroutine 1 done")
// 向c1发送信号,通知第二个goroutine可以开始
c1 <- struct{}{}
}()
// 第二个goroutine
go func() {
// 等待第一个goroutine的信号
<-c1
fmt.Println("goroutine 2 start")
// 模拟一些工作
fmt.Println("goroutine 2 done")
// 向c2发送信号,通知第三个goroutine可以开始
c2 <- struct{}{}
}()
// 第三个goroutine
go func() {
// 等待第二个goroutine的信号
<-c2
fmt.Println("goroutine 3 start")
// 模拟一些工作
fmt.Println("goroutine 3 done")
}()
// 防止主线程退出
select {}
}
在上述代码中:
c1
和c2
是无缓冲的Channel,用于传递信号。- 每个goroutine在完成自己的工作后,通过相应的Channel发送信号,而下一个goroutine在开始工作前,会先从对应的Channel接收信号,从而实现按顺序执行。
select {}
用于阻塞主线程,防止程序在goroutine完成之前退出。