Concurrency 为什么在同一goroutine中使用无缓冲通道会导致死锁?
我确信对于这种琐碎的情况有一个简单的解释,但我对Concurrency 为什么在同一goroutine中使用无缓冲通道会导致死锁?,concurrency,go,channels,Concurrency,Go,Channels,我确信对于这种琐碎的情况有一个简单的解释,但我对go并发模型是新手 当我运行这个示例时 package main import "fmt" func main() { c := make(chan int) c <- 1 fmt.Println(<-c) } 为什么? 包装c来自: 如果通道无缓冲,发送方将阻塞,直到接收方收到该值。如果通道有一个缓冲区,发送方只会阻塞,直到值 已复制到缓冲区;如果缓冲区已满,这意味着 等待某个接收器检索到
go
并发模型是新手
当我运行这个示例时
package main
import "fmt"
func main() {
c := make(chan int)
c <- 1
fmt.Println(<-c)
}
为什么?
包装
c来自:
如果通道无缓冲,发送方将阻塞,直到接收方收到该值。如果通道有一个缓冲区,发送方只会阻塞,直到值
已复制到缓冲区;如果缓冲区已满,这意味着
等待某个接收器检索到值
如果不是这样说的话:
- 当一个通道已满时,发送方等待另一个goroutine通过接收来腾出一些空间
- 您可以将无缓冲通道视为始终满的通道:必须有另一个goroutine来接收发送方发送的内容
这条线
c <- 1
这样在通道阻塞之前,通道中就有一个项目的空间
但这不是并发的意义所在。通常情况下,如果没有其他goroutine,您不会使用频道来处理您放入的内容。您可以这样定义一个接收goroutine:
func main() {
c := make(chan int)
go func() {
fmt.Println("received:", <-c)
}()
c <- 1
}
func main(){
c:=制造(成交量)
go func(){
fmt.Println(“已接收:”,在无缓冲通道中写入通道将不会发生,直到必须有某个接收器正在等待接收数据,这意味着在下面的示例中
func main(){
ch := make(chan int)
ch <- 10 /* Main routine is Blocked, because there is no routine to receive the value */
<- ch
}
func main(){
ch:=制造(成交量)
ch在这个答案中,我将尝试解释错误消息,通过它我们可以稍微了解go在通道和Goroutine方面是如何工作的
第一个例子是:
package main
import "fmt"
func main() {
c := make(chan int)
c <- 1
fmt.Println(<-c)
}
在代码中,根本没有goroutine(顺便说一句,这个错误是在运行时,而不是编译时)
缓冲消除了同步
缓冲使它们更像Erlang的邮箱
缓冲通道在某些问题上可能很重要,但它们更难以推理
默认情况下,通道是无缓冲的,这意味着它们只接受发送
(chan我觉得很难想象,有三种情况:1)没有新goroutine的无缓冲通道->死锁,2)无新goroutine->无死锁的缓冲通道3)有新goroutine->运行的无缓冲通道。当通道已满时,必须有一个goroutine来接收发送方发送的内容,否则发送方会阻止,直到有一个来。您可以将无缓冲通道视为始终满的通道。尝试将该通道想象为物理管道:如果是太短或太满,你必须等待另一端的人拿东西,或者把东西放进去会使一些内容掉到地上。goroutines的另一个有用的类比是将它们与硬件电路中的逻辑门进行比较,通道就是电线。在问题的示例中,“门”的接线错误,没有连接到o本身可以发送或接收,但不能同时发送或接收。这不是说无缓冲通道总是满的。相反,它们根本不满。通道就像Goroutine之间的电缆。它们没有缓冲区。只有通道的输入和输出点可能有称为缓冲区的存储桶。这不是真的:“在无缓冲通道中,只有当某个接收器正在等待接收数据时,才会写入通道“。写入通道将发生,当接收器出现时,它将接收数据,如果没有,则会死锁或泄漏等。@InAcgumus,在上面的第三个代码片段中,接收器稍后会出现,但死锁:当你从同一个电话号码呼叫你的电话号码时会发生什么?死锁或忙音等。这里的情况相同。”。
func main() {
c := make(chan int)
go func() {
fmt.Println("received:", <-c)
}()
c <- 1
}
func main(){
ch := make(chan int)
ch <- 10 /* Main routine is Blocked, because there is no routine to receive the value */
<- ch
}
func main(){
ch :=make(chan int)
go task(ch)
ch <-10
}
func task(ch chan int){
<- ch
}
func main(){
ch := make(chan int)
ch <- 10 /*Blocked: No routine is waiting for the data to be consumed from the channel */
go task(ch)
}
func main(){
ch := make(chan int, 1) /*channel of size 1 */
ch <-10 /* Not blocked: can put the value in channel buffer */
<- ch
}
func main(){
ch := make(chan int, 1) /*channel Buffer size 1 */
ch <- 10
ch <- 20 /*Blocked: Because Buffer size is already full and no one is waiting to recieve the Data from channel */
<- ch
<- ch
}
package main
import "fmt"
func main() {
c := make(chan int)
c <- 1
fmt.Println(<-c)
}
fatal error: all goroutines are asleep - deadlock!