【阅读总结】Understanding Real-World Concurrency Bugs in Go 小结

最近希望深入一下go 语言细节,在看过基本的语法后,开始找相关经典文章去阅读。虽然阅读总结大部分由GPT生成,但是我认为作为提示词和学习路径,还是有必要记录一下的。

个人总结在此:

以下文章由GPT生成,没有个人思考与总结。


《Understanding Real-World Concurrency Bugs in Go》由Tengfei Tu等人撰写。论文首次对Go语言实际程序中的并发错误进行了系统研究,分析171个并发错误,发现消息传递并不比共享内存更不易出错,某些情况下甚至更容易导致错误,研究结果有助于理解Go语言并发模型,为编写可靠的Go程序和开发调试诊断工具提供指导。

  1. 背景与研究目的:Go语言旨在简化并发编程,但其新的并发原语和机制对并发错误的影响尚不明确。本文通过对6个开源Go应用的研究,分析并发错误的成因、修复方法,比较消息传递和共享内存两种通信机制的易错性,为Go语言并发编程提供指导。
  2. Go语言并发机制与应用
  • 并发单元 - Goroutine:Go使用Goroutine作为并发单元,它是轻量级用户级线程,可通过在函数调用前加go关键字创建,支持匿名函数创建Goroutine,可能引发数据竞争。
  • 同步机制:支持共享内存同步,提供Mutex、RWMutex等原语;Once确保函数只执行一次;WaitGroup用于多个Goroutine完成共享变量访问的同步。还通过通道(chan)实现消息传递,有缓冲和无缓冲通道之分,select语句可用于等待多个通道操作。
  • 研究应用:选取Docker、Kubernetes等6个具有代表性的Go语言应用,这些应用在数据中心环境广泛使用,开发历史长且规模较大。
  1. Go语言并发使用模式
  • Goroutine使用:静态分析显示,6个应用中Goroutine创建频繁,平均每千行代码创建0.18 - 0.83个,多数应用使用匿名函数创建Goroutine更多。动态分析表明,与gRPC - C相比,gRPC - Go在运行时创建更多Goroutine,且Goroutine执行时间更短。
  • 并发原语使用:共享内存同步操作使用频率高于消息传递,Mutex是使用最广泛的原语,消息传递中chan使用频率最高。gRPC - Go使用的并发原语数量和种类均多于gRPC - C,且各应用并发原语使用情况随时间趋于稳定。
  1. 错误研究方法 - 错误收集:通过在GitHub提交历史中搜索并发相关关键词,筛选出3211个匹配提交,随机抽样并人工研究,最终确定171个并发错误。
  • 错误分类:根据错误行为分为阻塞错误(一个或多个Goroutine执行受阻)和非阻塞错误(Goroutine能完成任务但行为不符合预期);根据错误原因分为共享内存错误和消息传递错误。
  • 错误重现:回滚应用版本,构建并运行有错误的程序,依据错误报告中的症状判断是否成功重现错误。
  1. 阻塞错误
  • 根源:约42%由共享内存保护错误导致,如Mutex误用、RWMutex特有的优先级问题、WaitGroup和Cond使用不当;58%由消息传递错误引起,包括通道使用错误、通道与其他阻塞原语配合不当、消息传递库使用错误。
  • 修复:多数共享内存相关错误修复方法与传统语言类似,消息传递相关错误常通过添加消息或关闭操作、添加select语句、更换通道类型等方式修复。错误原因与修复策略、修复使用的原语有较高相关性,修复补丁平均6.8行代码。
  • 检测:Go内置死锁检测器只能检测出2个阻塞错误,因其设计目标为最小化运行时开销,未考虑部分运行中的Goroutine和等待其他系统资源的Goroutine,未来需开发新的检测技术。
  1. 非阻塞错误
  • 根源:约80%由共享内存保护失败引起,包括传统问题和Go新特性导致的问题,如匿名函数使用不当、WaitGroup误用、特殊库使用不当;约20%由消息传递错误引起,如通道误用、特殊库中通道使用不当。
  • 修复:约69%通过限制时间修复,如添加同步原语或移动现有原语;部分通过消除或绕过共享变量访问指令、复制共享变量等方式修复。Mutex和channel是常用的修复原语。
  • 检测:Go数据竞争检测器使用happen - before算法,能检测部分传统错误和匿名函数导致的错误,但因非阻塞错误类型多样、算法依赖Goroutine交错执行、存储历史信息有限等原因,无法检测所有非阻塞错误。
  1. 讨论与展望:消息传递不一定比共享内存更不易出错,它是阻塞错误的主要原因,且与其他机制结合时难以检测。研究揭示的错误代码模式可用于并发错误检测,未来应结合静态和动态技术开发更有效的检测工具。
  2. 结论:首次全面实证研究Go语言并发错误,发现消息传递和共享内存都可能导致并发错误,期望研究能加深对Go并发错误的理解,引起更多关注。
相关推荐
brzhang8 分钟前
A2UI:但 Google 把它写成协议后,模型和交互的最后一公里被彻底补全
前端·后端·架构
lsx20240613 分钟前
C语言中的强制类型转换
开发语言
coderHing[专注前端]16 分钟前
告别 try/catch 地狱:用三元组重新定义 JavaScript 错误处理
开发语言·前端·javascript·react.js·前端框架·ecmascript
开心猴爷31 分钟前
iOS App 性能测试中常被忽略的运行期问题
后端
星辰烈龙35 分钟前
黑马程序员Java基础9
java·开发语言
SHERlocked931 小时前
摄像头 RTSP 流视频多路实时监控解决方案实践
c++·后端·音视频开发
@游子1 小时前
Python类属性与魔术方法全解析
开发语言·python
AutoMQ1 小时前
How does AutoMQ implement a sub-10ms latency Diskless Kafka?
后端·架构
Rover.x1 小时前
Netty基于SpringBoot实现WebSocket
spring boot·后端·websocket
疯狂的程序猴1 小时前
用 HBuilder 上架 iOS 应用时如何管理Bundle ID、证书与描述文件
后端