一、面试题相关
1.什么是CSP?
CSP(Communicating Sequential Processes 通信顺序进程)是一种基于通信的并发理论,它的核心思想是:通过通信共享内存,而不是通过共享内存来通信。
具有以下特点:
1. 避免共享内存: 协程 (Goroutine) 不直接修改变量,而是通过 Channel 通信。
2. 天然同步:Channel 的发送/接收自带同步机制,无需手动加锁
3. 易于组合:Channel可以嵌套使用,构建复杂并发模式(如管道、超时控制)
2. Channel的底层实现原理是怎样的?
分析:
channel的底层实现是一个hchan的结构,hchan的结构定义。
type hchan struct {
qcount uint // 当前队列中剩余的元素个数
dataqsiz uint // 环形队列的大小,即可以缓存的元素数量(make(chan T, N) 中的 N)
buf unsafe.Pointer // 指向环形队列的指针(有缓冲 channel 才非 nil)
elemsize uint16 // 每个元素的大小
closed uint32 // channel 是否已关闭的标志
elemtype *_type // 元素类型,用于在运行时进行类型检查
sendx uint // 发送索引(send index),指向环形队列中下一个要发送的位置
recvx uint // 接收索引(receive index),指向环形队列中下一个要接收的位置
recvq waitq // 等待接收的 goroutine 队列(链表结构)
sendq waitq // 等待发送的 goroutine 队列(链表结构)
lock mutex // 互斥锁,保护 hchan 中的所有字段
}
// waitq 是一个 sudog 的链表,sudog 代表了一个等待中的 goroutine
type waitq struct {
first *sudog
last *sudog
}
回答:
Channel的底层是一个名为 hchan 的结构体, 核心包含几个关键组件:
环形缓冲区buf : 有缓冲channel内部维护一个固定大小的环形队列, 用 buf 指针指向缓冲区, sendx 和recvx 分别记录发送和接收的位置索引。这样设计能高效利用内存,避免数据搬移。
两个等待队列 sendq和recvq:用来管理阻塞的goroutine。sendq 存储因channel满而阻塞的发送者,recvq 存储因channel空而阻塞的接收者。 这些队列用双向链表实现, 当条件满足时会唤醒对应的goroutine。
互斥锁:hchan 内部有个mutex,所有的发送、接收操作都需要先获取锁,用来保证并发安全。虽然看起来可能影响性能,但Go的调度器做了优化,大多数情况下锁竞争并不激烈。

补充讲一下等待队列
1. 发送等待队列 (sendq)
作用:存储所有因无法立即发送数据而被阻塞的 goroutine。
触发条件:
无缓冲 Channel:没有接收者在等待时
有缓冲 Channel:缓冲区已满时
队列中的元素:每个被阻塞的发送者 goroutine 被打包成一个 sudog 节点。
2. 接收等待队列 (recvq)
作用:存储所有因无法立即接收数据而被阻塞的 goroutine。
触发条件:
无缓冲 Channel:没有发送者在等待时
有缓冲 Channel:缓冲区为空时
队列中的元素:每个被阻塞的接收者 goroutine 被打包成一个 sudog 节点。

最低0.47元/天 解锁文章
1629

被折叠的 条评论
为什么被折叠?



