Golang Go语言中关于无缓冲 channel 的 deadlock 问题
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
一个堵塞一个死锁,就因为 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)问题。
死锁通常发生在以下情况:
-
双向阻塞:如果两个或更多的goroutine相互等待对方通过无缓冲channel发送或接收数据,而这些操作又没有其他触发条件,那么这些goroutine将永远阻塞下去,形成死锁。
-
资源竞争:当多个goroutine试图同时访问同一个无缓冲channel,而没有一个明确的顺序或超时机制时,也可能导致死锁。
为了避免无缓冲channel引发的死锁问题,可以采取以下措施:
- 确保每个发送操作都有对应的接收操作,反之亦然。
- 使用有缓冲(buffered)channel来存储临时数据,但需注意缓冲区大小,以避免溢出。
- 引入超时机制,如使用
select
语句配合time.After
来设置操作超时。 - 设计合理的并发模型,确保goroutine之间的依赖关系清晰,避免循环等待。
总之,无缓冲channel在Go语言中是一个强大的同步工具,但使用时需谨慎,以避免死锁等并发问题。