无缓冲的通道会阻塞接收器,直到通道上有数据可用为止。我不清楚同一通道上的多个接收器(例如使用 goroutine 时)的阻塞行为如何。我确信只要该通道上没有发送数据,它们都会阻塞。
但是,一旦我向该通道发送单个值会发生什么?哪个接收器/协程将获取数据并因此解锁?他们全部?第一个排队?随机?
一个随机(非确定性)的人将收到它。
查看语言规范:
“select”语句的执行分几个步骤进行:
- 对于语句中的所有情况,接收操作的通道操作数以及发送的通道和右侧表达式 输入时,语句按源顺序仅计算一次 “选择”语句。结果是一组接收通道 from 或 send to,以及要发送的相应值。任意一侧 无论哪种情况(如果有),该评估都会产生影响 选择通信操作进行。表达式关于 RecvStmt 的左侧带有短变量声明或 作业尚未评估。
- 如果一个或多个通信可以继续进行,则通过统一的伪随机选择来选择一个可以继续进行的通信。 否则,如果存在默认情况,则选择该情况。如果有 没有默认情况下,“select”语句会阻塞,直到至少一个 的通信可以继续进行。
- 除非选择的情况是默认情况,否则执行相应的通信操作。
- 如果选定的情况是带有短变量声明或赋值的 RecvStmt,则左侧表达式为 评估并分配接收到的值(或多个值)。
- 执行所选案例的语句列表。
如果程序允许多个 goroutine 在单个通道上接收,则发送者正在广播。每个接收器应该同样能够处理数据。因此,go 运行时使用什么机制来决定众多 goroutine 接收器中的哪一个将运行并不重要。但如果通道未缓冲,则只会为每个发送的项目运行一个。
另请参阅:https://github.com/golang/go/issues/247,尤其是用户 josef.svenningsson 的推荐:
如果没有指定顺序,则可以自由实施 让一个进程完全挨饿,我认为没有人会这样做 高兴。某种公平保证对于 以确保所有 goroutine 都可以尝试进行评估。 所以,这不是能够控制顺序的问题 事情正在发生。我担心的是有些 goroutine 可能永远不会得到 如果接收者之间的顺序未定义,则有机会完成其工作。
但是Go内存模型中所确定的是,它最多只是其中之一。
特定通道上的每个发送都与来自该通道的相应接收相匹配,通常在不同的 goroutine 中。
这并不像我想要的那么清晰,但稍后他们给出了信号量实现的示例
var limit = make(chan int, 3)
func main() {
for _, w := range work {
go func(w func()) {
limit <- 1
w()
// if it were possible for more than one channel to receive
// from a single send, it would be possible for this to release
// more than one "lock", making it an invalid semaphore
// implementation
<-limit
}(w)
}
select{}
}