这是a previous thread with a similar name的后续内容。
它有一个公认的答案,但答案并没有真正回答这个问题。从该线程,这是用例:
if len(myChannel) > 0 {
// Possible issue here: length could have changed to 0 making this blocking
elm := <- myChannel
return elm
}
OP将其称为“可能的问题”,但它是一个确定的问题:一种竞争条件,其中另一个消费者可能在评估if条件和执行两个语句之间从通道中提取了一个值。
现在,我们被告知Go Way是支持频道而不是互斥,但是在这里我们似乎无法实现基本的非阻塞读取(通过轮询长度和原子读取)而不将互斥锁和通道配对在一起,并且使用我们的新并发数据类型而不是通道。
那可能是对的吗?是否真的没有办法可靠地确保recv不会通过提前检查空间来阻止? (与Java中的BlockingQueue.poll()或其他基于队列的消息传递IPC工具中的类似工具相比......)
答案 0 :(得分:9)
这正是select
中的默认案例:
var elm myType
select {
case elm = <-myChannel:
default:
}
return elm
如果可以,则指定elm
,否则返回零值。有关更为广泛的示例,请参阅Effective Go中的“泄漏缓冲区”。
答案 1 :(得分:2)
Rob Napier的回答是正确的。
但是,假设它是一种反模式,你可能很难实现非阻塞行为。
使用Go,您不必须担心阻止。来吧,阻止没有内疚。它可以使代码更容易编写,尤其是在处理i / o时。
CSP允许您设计数据驱动的并发程序,这些程序可以很好地扩展(因为没有使用过多的互斥量)。通过通道进行通信的一小组goroutine可以表现得像一个更大系统的组件;这些组件(也通过通道进行通信)可以分组为更大的组件;这种模式在不断增加的规模上重复。
传统上,人们从顺序代码开始,然后尝试通过添加goroutines,channel,mutex等来添加并发性。作为练习,尝试不同的东西:尝试将系统设计为最大并发 - 使用尽可能深入的goroutines和渠道。您可能对您实现的性能不感兴趣...因此可能会尝试考虑如何通过组合(而不是划分)块来改进它,从而减少总数goroutines,从而实现更优化的并发性。