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!