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