【golang源码分析】chan底层原理——附带读写用户队列的环形缓冲区

本文详细探讨了Go语言中Channel的工作原理,包括环形缓冲区结构、读写机制及内部数据结构。阐述了有缓冲与无缓冲Channel的区别,以及关键源码分析,帮助读者深入理解Go并发模型。

1 环形缓冲区

1.1 环形缓冲区结构

       环形缓冲区通常有一个读指针和一个写指针。读指针指向环形缓冲区中可读的数据,写指针指向环形缓冲区中可写的缓冲区。通过移动读指针和写指针就可以实现缓冲区的数据读取和写入。在通常情况下,环形缓冲区的读用户仅仅会影响读指针,而写用户仅仅会影响写指针。如果仅仅有一个读用户和一个写用户,那么不需要添加互斥保护机制就可以保证数据的正确性。如果有多个读写用户访问环形缓冲区,那么必须添加互斥保护机制来确保多个用户互斥访问环形缓冲区。

1.2 环形缓冲区一种读写实现机制

一般的,圆形缓冲区需要4个指针

  • 在内存中实际开始位置;

  • 在内存中实际结束位置,也可以用缓冲区长度代替;

  • 存储在缓冲区中的有效数据的开始位置(读指针);

  • 存储在缓冲区中的有效数据的结尾位置(写指针)。

缓冲区是满、或是空,都有可能出现读指针与写指针指向同一位置:

缓冲区中总是有一个存储单元保持未使用状态。缓冲区最多存入(size-1)个数据。如果读写指针指向同一位置,则缓冲区为空。如果写指针位于读指针的相邻后一个位置,则缓冲区为满。

 

 

 

2 chan内部数据结构

2.1 chan的数据结构

chan实质是个环形缓冲区,外加一个接受者协程队列和一个发送者协程队列

  • buf      :环形缓冲区
  • sendx :用于记录buf这个循环链表中的发送的index
  • recvx  :用于记录buf这个循环链表中接收的index
  • recvq  :接受者协程队列
  • sendq :发送者协程队列
  • lock    :互斥锁

2.2 有缓冲区和无缓冲区chan的区别

2.2.1 无缓冲chan数据同步过程和sudog结构

  1. 创建一个发送者列表和接收者列表都为空的 channel。
  2. 第一个协程向 channel 发送变量的值
  3. channel 从池中获取一个sudog结构体变量,用于表示发送者。sudog 结构体会保持对发送者所在协程的引用,以及发送变量的引用。
  4. 发送者加入sendq队列。<
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值