Golang Go语言中关于无缓冲 channel 的 deadlock 问题

发布于 1周前 作者 ionicwang 来自 Go语言

package main

import ( "fmt" "net" )

var temp net.IP

func main() { fmt.Println("start......") ch := make(chan int) <-ch fmt.Println("hello world") }

/* start......

*/

package main

import ( "fmt" )

func main() { fmt.Println("start......") ch := make(chan int) <-ch fmt.Println("hello world") }

/* start...... fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]: main.main() */


Golang Go语言中关于无缓冲 channel 的 deadlock 问题

更多关于Golang Go语言中关于无缓冲 channel 的 deadlock 问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

11 回复

一个堵塞一个死锁,就因为 net 包?

更多关于Golang Go语言中关于无缓冲 channel 的 deadlock 问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


第一个应该也是死锁,没有创建新的协程,主协程阻塞。
去 play ground 试试?

我是在本地环境运行的,play ground 会死锁,但是本地没有

引用 cgo 的包(包括 net )就会关闭死锁检测器

这个说法有参考资料吗,亲

无论是否 import net ,我这里都是 17 没有报错,18 报错

知道了,net 没有 cgo ,可以 import "C"来检测

go1.18.1 复现。。

在Golang中,无缓冲(unbuffered)channel 是指在发送(send)操作与接收(receive)操作之间不存储数据的通道。这种设计意味着发送操作会一直阻塞,直到另一方准备好接收数据;同样,接收操作也会一直阻塞,直到另一方发送了数据。这种机制虽然有助于确保数据的一致性和同步,但如果不小心使用,很容易导致死锁(deadlock)问题。

死锁通常发生在以下情况:

  1. 双向阻塞:如果两个或更多的goroutine相互等待对方通过无缓冲channel发送或接收数据,而这些操作又没有其他触发条件,那么这些goroutine将永远阻塞下去,形成死锁。

  2. 资源竞争:当多个goroutine试图同时访问同一个无缓冲channel,而没有一个明确的顺序或超时机制时,也可能导致死锁。

为了避免无缓冲channel引发的死锁问题,可以采取以下措施:

  • 确保每个发送操作都有对应的接收操作,反之亦然。
  • 使用有缓冲(buffered)channel来存储临时数据,但需注意缓冲区大小,以避免溢出。
  • 引入超时机制,如使用select语句配合time.After来设置操作超时。
  • 设计合理的并发模型,确保goroutine之间的依赖关系清晰,避免循环等待。

总之,无缓冲channel在Go语言中是一个强大的同步工具,但使用时需谨慎,以避免死锁等并发问题。

回到顶部