侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1824 篇文章
  • 累计收到 0 条评论

使用无缓冲 Channel 实现两个 Goroutine 的同步

2025-12-11 / 0 评论 / 3 阅读

题目

使用无缓冲 Channel 实现两个 Goroutine 的同步

信息

  • 类型:问答
  • 难度:⭐

考点

无缓冲 Channel 特性, Goroutine 同步, Channel 阻塞机制

快速回答

通过无缓冲 Channel 的阻塞特性实现 Goroutine 同步:

  • 无缓冲 Channel 发送和接收操作会相互阻塞
  • 先启动的 Goroutine 在发送数据时会阻塞,直到另一个 Goroutine 准备好接收
  • 通过这种机制确保两个 Goroutine 按顺序执行
## 解析

原理说明

无缓冲 Channel 的特性是:发送操作会阻塞直到有 Goroutine 接收数据,接收操作会阻塞直到有 Goroutine 发送数据。利用这个特性可以实现 Goroutine 间的同步,确保执行顺序。

代码示例

package main

import "fmt"

func main() {
    // 创建无缓冲 channel
    ch := make(chan struct{})

    // Goroutine 1
    go func() {
        fmt.Println("Goroutine 1 执行")
        ch <- struct{}{} // 发送信号(阻塞直到被接收)
    }()

    // Goroutine 2
    go func() {
        <-ch // 接收信号(阻塞直到有数据)
        fmt.Println("Goroutine 2 执行")
    }()

    // 防止主 Goroutine 提前退出
    var input string
    fmt.Scanln(&input)
}

执行结果

Goroutine 1 执行
Goroutine 2 执行

关键机制

  • 阻塞同步:Goroutine1 在 ch <- struct{}{} 处阻塞,直到 Goroutine2 执行 <-ch
  • 执行顺序保证:Goroutine2 必须等到接收数据后才能继续执行

最佳实践

  • 使用 struct{}{} 作为信号量(零内存开销)
  • 明确 channel 的发送/接收方职责
  • 对于复杂同步场景可结合 sync.WaitGroup

常见错误

  • 忘记接收导致死锁(所有 Goroutine 阻塞)
  • 在主 Goroutine 中误用无缓冲 channel 导致阻塞
  • 未处理可能的 channel 泄漏

扩展知识

  • 有缓冲 Channel:当缓冲区未满时发送不阻塞,可实现异步通信
  • Channel 关闭原则:由发送方关闭 channel,接收方通过 v, ok := <-ch 判断状态
  • Select 语句:用于同时监控多个 channel 的状态