4种Golang并发操作中常见的死锁情形
2023-09-14 09:05:46 时间
摘要:什么是死锁,在Go的协程里面死锁通常就是永久阻塞了,你拿着我的东西,要我先给你然后再给我,我拿着你的东西又让你先给我,不然就不给你。我俩都这么想,这事就解决不了了。
本文分享自华为云社区《Golang并发操作中常见的死锁情形》,作者:Regan Yue 。
什么是死锁,在Go的协程里面死锁通常就是永久阻塞了,你拿着我的东西,要我先给你然后再给我,我拿着你的东西又让你先给我,不然就不给你。我俩都这么想,这事就解决不了了。
第一种情形:无缓存能力的管道,自己写完自己读
先上代码:
func main() {
ch := make(chan int, 0)
ch <- 666
x := <- ch
fmt.Println(x)
}
我们可以看到这是一个没有缓存能力的管道,然后往里面写666,然后就去管道里面读。这样肯定会出现问题啊!一个无缓存能力的管道,没有人读,你也写不了,没有人写,你也读不了,这正是一种死锁!
fatal error: all goroutines are asleep - deadlock!
解决办法很简单,开辟两条协程,一条协程写,一条协程读。
第二种情形:协程来晚了
func main() {
ch := make(chan int,0)
ch <- 666
go func() {
<- ch
}()
}
我们可以看到,这条协程开辟在将数字写入到管道之后,因为没有人读,管道就不能写,然后写入管道的操作就一直阻塞。这时候你就有疑惑了,不是开辟了一条协程在读吗?但是那条协程开辟在写入管道之后,如果不能写入管道,就开辟不了协程。
第三种情形:管道读写时,相互要求对方先读/写
如果相互要求对方先读/写,自己再读/写,就会造成死锁。
func main() {
chHusband := make(chan int,0)
chWife := make(chan int,0)
go func() {
select {
case <- chHusband:
chWife<-888
}
}()
select {
case <- chWife:
chHusband <- 888
}
}
先来看看老婆协程,chWife只要能读出来,也就是老婆有钱,就给老公发个八百八十八的大红包。
再看看老公的协程,一看不得了,咋啦?老公也说只要他有钱就给老婆包个八百八十八的大红包。
两个人都说自己没钱,老公也给老婆发不了红包,老婆也给老公发不了红包,这就是死锁!
第四种情形:读写锁相互阻塞,形成隐形死锁
先来看一看代码:
func main() {
var rmw09 sync.RWMutex
ch := make(chan int,0)
go func() {
rmw09.Lock()
ch <- 123
rmw09.Unlock()
}()
go func() {
rmw09.RLock()
x := <- ch
fmt.Println("读到",x)
rmw09.RUnlock()
}()
for {
runtime.GC()
}
}
这两条协程,如果第一条协程先抢到了只写锁,另一条协程就不能抢只读锁了,那么因为另外一条协程没有读,所以第一条协程就写不进。
如果第二条协程先抢到了只读锁,另一条协程就不能抢只写锁了,那么因为另外一条协程没有写,所以第二条协程就读不到。
相关文章
- 并发数据结构-1.5 链表
- 并发数据结构-1.4 池
- 线程同步工具(六)控制并发阶段性任务的改变
- 并发集合(九)使用原子 arrays
- Golang并发模型:流水线模型
- java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器
- HashMap在高并发下如果没有处理线程安全会有怎样的安全隐患,具体表现是什么
- [Go] Golang并发控制: WaitGroup 含义和常规用法
- 如何使用jMeter对需要CSRF token验证的OData服务进行并发性能测试
- 说说Golang goroutine并发那些事儿
- TCP 网络编程 TCP C/S 架构 socket connect send recv bind listen accept 三次握手 四次挥手 多进程实现并发
- Java并发编程:volatile关键字解析
- Java并发编程核心概念一览
- 【高并发】终于弄懂为什么局部变量是线程安全的了!!
- Go语言自学系列 | golang并发编程之原子变量的引入
- Go语言自学系列 | golang并发编程之select switch
- Go语言自学系列 | golang并发编程之Mutex互斥锁实现同步
- Go语言自学系列 | golang并发编程之runtime包
- 高并发必备篇(二)——线程为什么会不安全?
- <<高并发系统实战课>> 小记随笔 —— 用户中心案例优化
- golang查看是否并发资源竞争
- golang_并发安全: slice和map并发不安全及解决方法
- Nginx支持比Apache高并发的原因