Go Channel

原理

  • 本质上,channel是一个包含:发送Go队列,接收Go队列,由循环数组实现的缓存数据队列,锁这几个元素组成的结构体实现;
  • sendmsg阶段:
    • 如果接收Go队列有值,则直接进行值元素的内存拷贝,并唤醒接收队列;
    • 如有缓冲队列且未满,则将值复制到循环队列中;
    • 如果有缓冲队列且满了或无缓冲队列,将协程放到channel的sendqueue中;
  • recvmsg阶段:
    • 如果缓冲,且无数据,则进入recvqueue中,协程挂起(gopack);
    • 如果缓冲队列中数据,由从队列中将值拷贝给当前接收者;
    • 如果sendqueue有协程,则说明缓冲队列已满,则从缓冲队列中取值,并将sendqueue中取一个协程,将其值拷贝到缓冲循环数组中;
  • 上述操作是在mutex锁下进行,所以channel是协程安全的;