Go中的实际并发错误

利用并发原语,协程和通道,Go语言尝试简化并发编程并使其减少出错的机会。但实际情况究竟是怎样的呢?幸运的是,多亏了来自加州大学圣地亚哥分校的 Yiying Zhang 副教授和来自宾夕法尼亚州立大学的 Linhai Song副教授等人的研究成果,我们可以从这两位作者的关于Go中的实际并发错误的文章中学习解惑。

共享内存 vs 通道

最早的分析之一是Go并发模式的使用。它概述了在Go构建的最大项目中如何使用共享内存原语(Mutex,RWMutex,atomic和condition变量)和新的并发原语(通道):

shared memory communication remains the top usage

由于使用情况随着时间的推移趋于稳定,因此该研究可能在接下来的几年中仍然有效。基于此,与并发原语相关的错误被提取出来:

然后,每个问题被检查一番以便了解错误的原因及需要哪种修复程序。

观察

这项研究的主要观察结果可能是开发人员认为通道将提供比传统同步技术更少的错误,但这并不总是对的:

含义2:与通常的看法相反,消息传递可能比共享内存引发更多的阻塞错误。我们呼吁注意消息传递编程中的潜在危险,也建议去关注该领域中的错误检测的研究问题。

尽管该研究表明通道中存在更多错误,但也展示出未来的前景更为广阔:

观察9:传统的共享内存同步技术仍然是Go中非阻塞性错误的主要修复方法,而通道不仅被广泛地用于修复与通道相关的错误,而且还被用于修复共享内存的错误。

重点

这项研究清楚地表明,新原语并不会减少并发环境中的错误数量。但是,通过更好地了解通道和协程的内部,这些问题可以很容易地被避免掉:

观察6:我们研究中的大多数阻塞错误(传统的共享内存错误和消息传递错误)都可以通过简单的解决方案来解决。

举个例子,下面是关于Docker的一个问题:

这个马虎的错误可以很轻松的通过运行go vet命令解决。

对Go生态系统作出的贡献

在研究期间,教授们发现静态代码检查器可能存在改善的空间:

含义3:Go阻塞错误的原因和修复之间的高度相关性及其修复的简单性表明,有希望开发出全自动或半自动化的工具在Go中修复 阻塞错误。

通过Go社区多年来获得的经验,runtime工具也可以得到改进:

含义4:简单的runtime死锁检测器在检测Go阻塞错误方面无效。未来的研究应侧重于构建新颖的阻塞错误检测技术,例如,结合使用静态和动态阻止模式检测。

从这些观察中,他们开始准备推出新的代码分析器。现在负责此项目的 Ziheng Liu一直推进此检查器的工作进展。这个检查器基于SSA包,并已通过在GraphQL Go项目中发现错误证明了其用处。 计划是在2020年1月发布该功能。

有关该研究的更多信息,可在Github上获得

#go

Go中的实际并发错误
1 Likes1.60 GEEK