当前位置: 首页 > news >正文

解决 Go 语言并发问题

        所有较为复杂的程序都会出现错误。当你意识到程序中存在一些异常情况时,启动调试会话通常不是你应该做的第一件事。本文将介绍一些无须使用调试器即可进行故障排除的技术。你可能会发现,尤其是在处理并发程序时,调试器有时并不能提供太多帮助,更有效的解决方案依赖于仔细阅读代码、日志和理解堆栈信息。

1. 解读堆栈跟踪信息

        如果幸运的话,当出现问题时,你的程序会出现恐慌,并输出大量诊断信息。之所以说你很幸运,是因为如果你有一个恐慌程序的输出,那么通常只需将它与源代码一起查看就可以找出问题所在。

        现在让我们来仔细研究一些堆栈跟踪信息。

1.1 哲学家进餐程序的死锁问题

        我们要讨论的第一个例子是哲学家进餐问题的一个容易出现死锁的实现,该程序中只有两个哲学家:

package mainimport ("sync"
)func philosopher(firstFork, secondFork *sync.Mutex) {for {firstFork.Lock()secondFork.Lock()secondFork.Unlock()firstFork.Unlock()}
}func main() {forks := [2]sync.Mutex{}go philosopher(&forks[1], &forks[0])go philosopher(&forks[0], &forks[1])select {}
}

        由于嵌套锁的循环性质,该程序最终会死锁。当发生这种情况时,运行时会检测到程序中没有剩余的活动 goroutine 并输出堆栈跟踪信息。

        该堆栈跟踪信息从根本原因开始:

fatal error: all goroutines are asleep - deadlock!

        然后它列出了所有活动的 goroutine,从引起恐慌的 goroutine 开始。在死锁的情况下,这可以是任何一个死锁的 goroutine。

        以下堆栈跟踪信息从 main 中的空 select 语句开始。它表明有一个 goroutine 正在等待该 select 语句:

goroutine 1 [select (no cases)]:
main.main()

第二个 goroutine 堆栈信息显示了该 goroutine 遵循的路径:

        可以看到,第一个条目来自运行时包,即未到出的 runtime_SemacquireMutex 函数,该函数使用了 3 个参数进行调用。带问号显示的参数是运行时无法可靠捕获的值,因为它们是在寄存器中传递的,而不是被推到堆栈上的。

1.2 链表指针问题

        现在让我们来看一个更有趣的恐慌。以下程序包含一个竞争条件,并且偶尔会出现恐慌:

package mainimport ("container/list""math/rand""sync"
)// This program occasionally panics
func main() {wg := sync.WaitGroup{}wg.Add(2)ll := list.New()// Goroutine that fills the listgo func() {defer wg.Done()for i := 0; i < 1000000; i++ {ll.PushBack(rand.Int())}}()// Goroutine that empties the listgo func() {defer wg.Done()for i := 0; i < 1000000; i++ {if ll.Len() > 0 {ll.Remove(ll.Front())}}}()wg.Wait()
}

        该程序包含两个 goroutine: 一个可以将元素添加到共享链表的末尾,另一个则从链表的开头删除元素。该程序通常可以正常运行直至完成,但有时它也会出现恐慌,其堆栈跟踪信息如下所示:

        正如我们试图在这里所演示的那样,充分了解发生恐慌的情况始终是最明智的。大多数时候,这需要你研究并找出有关底层数据结构的假设。就像上面的链表示例一样,如果数据结构被编写为不能有 nil 指针,那么当你看到 nil 指针时,所考虑的就不应该是添加 nil 检查,而是要尝试理解为什么最终会出现 nil 指针。

2. 检测故障并修复

        尽管付出了努力来进行测试,但大多数软件系统还是会出现问题。这表明通过测试可以实现的目标是有限的。之所以有限主要源于有关复杂软件系统的几个事实:

        首先,任何较为复杂的系统都需要与其环境进行交互,枚举系统运行的所有可能环境是不切实际的(并且在许多情况下这完全就是不可能的)。

        其次,你也许可以测试某个系统以确保其按预期运行,但通过测试以确保系统不会出现意外行为则要困难得多。

        此外,并发也增加了额外的复杂性:在特定场景下测试成功的程序在投入生产环境时可能会在相同场景下失败。

2.1 正确认识失败

        坦率地说,无论你对程序进行过多少次测试,所有足够复杂的程序最终都会失败。因此,构建系统以实现优雅的故障处理和快速恢复是有意义的。该架构的一部分用于检测异常并在可能的情况下修复异常的基础设施。云

相关文章:

  • 我问GPT flutter
  • 2024年10月湖北省自学考试报名流程(5步)
  • LLM概念梳理(一):训练流程之PT、SFT和PO
  • OriginPro快速上手指南:数据可视化与分析的利器
  • Android笔试面试题AI答之Kotlin(18)
  • 本科生毕业答辩全攻略:从开题到终期答辩的全面指南
  • 中国第一起名大师的老师颜廷利: 名字中的姓氏家谱字辈的最新解析
  • Vitis AI 进阶认知(Torch量化基础+映射+量化参数+对称性+每通道+PTQ+QAT+敏感性)
  • PHP进阶篇(奇怪的知识又增加了)
  • 局部整体(三)利用python绘制饼图
  • PostgreSQL-04-入门篇-连接多张表
  • 【微服务】Nacos配置中心和客户端数据同步模式
  • Vue3项目开发——新闻发布管理系统(一)
  • 《黑神话:悟空》总销量已破 450 万份,总销售额超过15亿元,对于单机游戏来说,这一成绩意味着什么?
  • 博途PLC手自动控制功能块(FB和FC完整SCL源代码)
  • .pyc 想到的一些问题
  • [deviceone开发]-do_Webview的基本示例
  • 【刷算法】从上往下打印二叉树
  • 4个实用的微服务测试策略
  • django开发-定时任务的使用
  • JavaScript类型识别
  • Leetcode 27 Remove Element
  • Linux快速复制或删除大量小文件
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • Node + FFmpeg 实现Canvas动画导出视频
  • node.js
  • python docx文档转html页面
  • Vue2.0 实现互斥
  • vue-cli在webpack的配置文件探究
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 聊聊redis的数据结构的应用
  • 什么软件可以剪辑音乐?
  • 学习HTTP相关知识笔记
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ​ArcGIS Pro 如何批量删除字段
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • #Datawhale AI夏令营第4期#AIGC文生图方向复盘
  • #define与typedef区别
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (zt)最盛行的警世狂言(爆笑)
  • (六) ES6 新特性 —— 迭代器(iterator)
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .NET Framework 3.5安装教程
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • .Net多线程总结
  • .net和jar包windows服务部署
  • .net后端程序发布到nignx上,通过nginx访问
  • .NET开发人员必知的八个网站
  • .NET业务框架的构建
  • .vimrc php,修改home目录下的.vimrc文件,vim配置php高亮显示