Hasty Briefsbeta

双语

Go Concurrency Distilled

10 hours ago
  • Goroutine 是使用 'go' 关键字启动的轻量级并发函数;Go 运行时将它们调度到操作系统线程上,main 也是一个 goroutine。
  • 使用 sync.WaitGroup 等待 goroutine 完成;Add 增加计数器,Done 减少计数器,Wait 阻塞直到计数器归零。
  • 通道允许 goroutine 传递值;它们可以是有缓冲或无缓冲的、有方向(发送/接收)的,关闭通道表示完成或停止进一步发送。
  • select 语句管理多个通道操作:它会阻塞直到某个 case 就绪,随机选择就绪的 case,并支持 default case 以实现非阻塞行为。
  • 管道通过通道连接 goroutine;done 通道或 context 可以发出取消信号,管道中的错误处理可以使用超时或专用结果通道。
  • context 包用于取消和超时;子 context 可以缩短父级的截止时间但不能延长,context.WithValue 传递调用范围内的值。
  • 当多个 goroutine 访问共享数据且其中至少一个进行修改时,会发生数据竞争;竞态检测器(go run -race)帮助发现它们,预防措施包括使用通道或互斥锁。
  • 竞态条件是并发操作不可预测交错导致的逻辑错误;它们不会被竞态检测器捕获,可能需要原子比较并交换或互斥锁。
  • 互斥锁(sync.Mutex、sync.RWMutex)保护共享数据;RWMutex 允许多个读者或一个写者,通道也可以用于互斥。
  • 信号量限制对资源的并发访问(使用缓冲通道或 sync.Semaphore);会合协调两个 goroutine,而屏障允许 N 个 goroutine 相遇。
  • sync.Cond 提供条件变量信号,使用 Wait/Signal/Broadcast;对于更灵活的的通知,通道可以实现发布/订阅模式。
  • sync.Once 确保函数只执行一次,用于一次性初始化;还提供了类似 OnceFunc 的便捷函数。
  • sync.Pool 是用于重用临时对象的对象池;它没有大小限制,项目可能被丢弃,因此只适用于生命周期短且没有强生命周期保证的对象。
  • sync/atomic 中的原子操作(例如 atomic.Int32)提供线程安全的单次操作,如 Load、Store、Add 和 CompareAndSwap;原子操作的组合不是原子的,可能需要互斥锁。
  • 并发代码的测试可以通过同步句柄(例如通道)或 synctest 包完成,后者模拟时间并允许你等待 goroutine 状态。
  • 调度:Go 运行时在较少的操作系统线程上运行许多 goroutine;GOMAXPROCS 控制线程数,调度器抢占长时间运行的 goroutine 以确保公平性。
  • 诊断包括 runtime/metrics 用于运行时统计,pprof 用于 CPU/堆分析,runtime/trace 用于跟踪并发事件;可以设置自动跟踪,使用滑动窗口。
  • 最终建议:使用 goroutine 执行任务,使用通道/select 进行通信,使用等待组同步,使用互斥锁保护共享状态,使用条件变量发出信号,使用 Once 进行一次性初始化。