Go Wiki: 使用 sync.Mutex 还是 channel?
Go 的一个座右铭是:“通过通信共享内存,而不是通过共享内存通信。”
话虽如此,Go 确实提供了 sync 包中的传统锁定机制。大多数锁定问题都可以通过 channel 或传统锁来解决。
那么应该使用哪种呢?
使用最能表达意图或最简单的。
Go 新手常见的错误是过度使用 channel 和 goroutine,仅仅因为可能,或者因为它很有趣。如果 sync.Mutex 更适合您的问题,请不要害怕使用它。Go 在让您使用最能解决您问题的工具方面是务实的,而不是强迫您使用一种代码风格。
但是,作为一般指南:
Channel | Mutex |
---|---|
传递数据所有权, 分发工作单元, 通信异步结果 | 缓存, 状态 |
如果您发现 sync.Mutex 的锁定规则变得过于复杂,请问自己是否使用 channel 会更简单。
Wait Group
另一个重要的同步原语是 sync.WaitGroup。这允许协作的 goroutine 在各自独立继续之前集体等待一个阈值事件。这通常在两种情况下有用。
首先,在“清理”时,可以使用 sync.WaitGroup 来确保所有 goroutine——包括主 goroutine——在所有 goroutine 干净地终止之前等待。
第二种更通用的情况是循环算法,该算法涉及一组 goroutine,它们各自独立工作一段时间,然后在屏障上等待,然后再独立继续。这种模式可能会重复多次。数据可能在屏障事件时交换。这种策略是 批量同步并行 (BSP) 的基础。
Channel 通信、互斥锁和等待组是互补的,可以结合使用。
更多信息
- Effective Go 中的 Channels:https://go-lang.org.cn/doc/effective_go#channels
- sync 包:https://pkg.go.dev/sync/
此内容是 Go Wiki 的一部分。