Go并发控制三种方法 | 青训营笔记

203 阅读1分钟

临近结课之余,本笔记旨在解决自己学习Go语言时留下的一个坑:既然Go语言是并发友好型语言,那么针对并发场景下的控制,Go语言提供了什么样优秀的解决关键字?
通过阅读Go圣经和相关图书,得出以下三种方案:

  • Channel 管道
  • WaitGroup 信号量
  • Context 上下文

其中管道的实现方式最简单,常用于协程间的通信;其次信号量可作为上限限制最大并发数;而上下文则能管理庞大的树状协程,是 gRPC-g o上我们常常见到的ctx。

先说明协程并发控制的概念,我这里的理解是:让协程该停下时停下,做正确的事。
  1. Channel 管道
    管道操作有两种方式:第一种写入,第二种读出。
    同时管道的存在形式也有两种方式:一是无缓冲,二是有缓冲。利用管道无缓冲的阻塞特性,我们可以实现对并发协程的控制。

  2. WaitGroup 信号量
    WaitGroup 对外提供了三个接口

    • Add(x int): 计数器+x(其数据结构维护一个 count 计数器,初始状态为0)
    • Wait(): 等待数量+1
    • Done(): 计数器-1

    通过信号量增减等待实现并发控制。

  3. Context 上下文
    Context 对外提供四个方法

    • Deadline():返回一个 deadline
    • Done():将 context 关闭,返回
    • Err()
    • Value()

    Context仅仅是一个接口定义,可以衍生出不同类型的 context,如以下三种类型:

    • cancelCtx:通过 WithCancel 方法创建
    • timerCtx:通过 WithDeadline 和 WithTimeout 方法创建
    • valueCtx:通过 WithValue 方法创建

    三种 context 实例可互为父节点。