MST

星途 面试题库

面试题:Go语言通道的死锁场景分析

以下是一段Go语言代码: ```go package main import ( "fmt" ) func main() { ch := make(chan int) ch <- 1 fmt.Println(<-ch) } ``` 请分析这段代码为什么会产生死锁,并提出至少两种避免死锁的方法,同时解释每种方法的原理。
31.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 死锁原因: 在Go语言中,向无缓冲通道发送数据(ch <- 1)时,会阻塞当前goroutine,直到有其他goroutine从该通道接收数据。在这段代码中,main函数是一个单独的goroutine,当执行到ch <- 1时,它会一直阻塞等待接收者,而后续的fmt.Println(<-ch)也在等待通道有数据可接收,由于没有其他goroutine来协助,就形成了死锁。
  2. 避免死锁的方法及原理
    • 方法一:使用缓冲通道
      package main
      
      import (
          "fmt"
      )
      
      func main() {
          ch := make(chan int, 1) // 创建有缓冲通道,缓冲大小为1
          ch <- 1
          fmt.Println(<-ch)
      }
      
      原理:有缓冲通道在发送数据时,如果缓冲区未满,不会阻塞发送者。这里创建的通道缓冲区大小为1,所以ch <- 1不会阻塞,后续的接收操作也能正常获取到数据。
    • 方法二:使用goroutine
      package main
      
      import (
          "fmt"
      )
      
      func main() {
          ch := make(chan int)
          go func() {
              ch <- 1
              close(ch) // 可以选择关闭通道,防止接收端一直阻塞等待新数据
          }()
          fmt.Println(<-ch)
      }
      
      原理:通过启动一个新的goroutine来发送数据,main函数所在的goroutine和新启动的goroutine并发执行。新的goroutine执行ch <- 1,而main函数执行fmt.Println(<-ch),它们之间的操作不会相互阻塞,从而避免了死锁。同时,关闭通道(close(ch))可以让接收者在没有更多数据时知道通道已关闭,避免一直阻塞。