4种Golang并发操作中常见的死锁情形
摘要:什么是死锁,在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()
}
}
这两条协程,如果第一条协程先抢到了只写锁,另一条协程就不能抢只读锁了,那么因为另外一条协程没有读,所以第一条协程就写不进。
如果第二条协程先抢到了只读锁,另一条协程就不能抢只写锁了,那么因为另外一条协程没有写,所以第二条协程就读不到。
4种Golang并发操作中常见的死锁情形的更多相关文章
- Mysql并发时经典常见的死锁原因及解决方法
1. mysql都有什么锁 MySQL有三种锁的级别:页级.表级.行级. 表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低. 行级锁:开销大,加锁慢:会出现死锁 ...
- MySQL学习笔记(五)并发时经典常见的死锁原因及解决方法
MySQL都有什么锁? MySQL有三种锁的级别:页级.表级.行级. 表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低. 行级锁:开销大,加锁慢:会出现死锁:锁定粒度 ...
- 数据结构和算法(Golang实现)(14)常见数据结构-栈和队列
栈和队列 一.栈 Stack 和队列 Queue 我们日常生活中,都需要将物品排列,或者安排事情的先后顺序.更通俗地讲,我们买东西时,人太多的情况下,我们要排队,排队也有先后顺序,有些人早了点来,排完 ...
- Golang并发原理及GPM调度策略(一)
其实从一开始了解到go的goroutine概念就应该想到,其实go应该就是在内核级线程的基础上做了一层逻辑上的虚拟线程(用户级线程)+ 线程调度系统,如此分析以后,goroutine也就不再那么神秘了 ...
- 数据结构和算法(Golang实现)(13)常见数据结构-可变长数组
可变长数组 因为数组大小是固定的,当数据元素特别多时,固定的数组无法储存这么多的值,所以可变长数组出现了,这也是一种数据结构.在Golang语言中,可变长数组被内置在语言里面:切片slice. sli ...
- 数据结构和算法(Golang实现)(15)常见数据结构-列表
列表 一.列表 List 我们又经常听到列表 List数据结构,其实这只是更宏观的统称,表示存放数据的队列. 列表List:存放数据,数据按顺序排列,可以依次入队和出队,有序号关系,可以取出某序号的数 ...
- 数据结构和算法(Golang实现)(16)常见数据结构-字典
字典 我们翻阅书籍时,很多时候都要查找目录,然后定位到我们要的页数,比如我们查找某个英文单词时,会从英语字典里查看单词表目录,然后定位到词的那一页. 计算机中,也有这种需求. 一.字典 字典是存储键值 ...
- 数据结构和算法(Golang实现)(17)常见数据结构-树
树 树是一种比较高级的基础数据结构,由n个有限节点组成的具有层次关系的集合. 树的定义: 有节点间的层次关系,分为父节点和子节点. 有唯一一个根节点,该根节点没有父节点. 除了根节点,每个节点有且只有 ...
- Java线程并发中常见的锁
随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想 ...
随机推荐
- nacos Failed to obtain JDBC Connection 连接异常
在conf/目录下,将application.properties.example 改名为bootstrap.properties 将连接数据库信息添加到末尾 # db mysql spring.da ...
- vscode源代码管理(vscode报错 未找到Git,请安装Git,或在"git.path" 设置中配置)
vscode源代码管理(vscode报错 未找到Git,请安装Git,或在"git.path" 设置中配置) 直接上图,电脑上已经安装git,由于vscode没有找到git,所以v ...
- Spring-初见
目录 组成 Spring Boot与Spring Cloud IOC DI 1.常量注入 2.Bean注入 3.Properties注入 p命名和c命名注入 Bean Singleton Protot ...
- Apache OfBiz 反序列化命令执行漏洞(CVE-2020-9496)
影响版本 - Apache Ofbiz:< 17.12.04 访问 https://192.168.49.2:8443/webtools/control/xmlrpc 抓包 进行数据包修改 pa ...
- Cookie、Session、JWT在koa中的应用及实现原理
目录 Cookie 重要属性 实现原理 cookie签名实现原理 注意事项 Session 实现原理 JWT 使用方式 组成 实际应用 实现原理 前端存储方式 cookie session local ...
- 使用html2canvas.js将HTML生成图片
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 一个故事看懂HTTPS
我是一个浏览器,每到夜深人静的时候,主人就打开我开始学习. 为了不让别人看到浏览记录,主人选择了"无痕模式". 但网络中总是有很多坏人,他们通过抓包截获我和服务器的通信,主人干了什 ...
- 用 区间判断(if)来猜价格的高低
1 #include <stdio.h> 2 #include <stdlib.h> 3 int main() 4 { 5 int price = 150; 6 int gue ...
- 一份热乎的字节跳动客户端面经,已拿Offer
字节面试过程: 4月4号进行内推,7天的简历评估,11号接到电话面试,尽管猝不及防回答仓促,但好在前期准备充分,通过.14号现场面试,次日收到通知,通过,二面.三面都很顺利.20号进行HR面,26号收 ...
- noip模拟35[第一次4题·裂了]
noip模拟35 solutions 这是我第一次这么正式的考四个题,因为这四个题都出自同一个出题人,并不是拼盘拼出来的. 但是考得非常的不好,因为题非常难而且一直想睡觉.. 有好多我根本就不会的算法 ...