高效Go并发编程 说明
# 前言
# 高效Go并发编程 说明
语言塑造我们的思维方式。我们处理问题和制定解决方案的方式,取决于我们能用语言表达的概念。编程语言也是如此。面对同一个问题,不同语言编写的解决方案程序可能会有所不同。本书主要讲述如何用Go语言表达并发算法来编写程序,以及理解这些程序的运行机制。
Go语言与许多流行语言的不同之处在于,它注重代码的可理解性。这和可读性不是一回事。许多用易读语言编写的程序,理解起来却并不容易。过去,我也掉进过这样的陷阱:使用那些让编程变得轻松的框架,编写结构井然有序的程序。但这种做法存在一个问题:程序编写完成后,它便开始了自己的 “生命历程”,其他人会接手维护工作。开发阶段积累的 “团队内部知识” 会流失,团队成员面对这个程序时,如果没有最初开发团队中最后一位成员的帮助,就无法理解它。开发程序和写小说没有太大区别。写小说是为了让别人阅读,程序也是如此。如果没人能理解你的程序,它就很难经得起时间的考验。
本书将尝试解释如何运用Go语言的并发结构进行思考,这样当你拿到一段代码时,就能明白程序的运行逻辑,同时别人也能理解你编写的内容。本书开篇会对并发以及Go语言对并发的处理方式进行高级概述。然后,会运用并发算法解决几个数据处理问题。毕竟,编写程序就是为了处理数据。我希望,通过观察在解决实际问题过程中并发模式是如何自然形成的,能帮助你掌握高效使用这门语言的技能。后面的章节会涉及更多示例,包括定时任务、周期性任务、服务器编程、流处理以及原子操作的实际应用。最后一章将讨论故障排查、调试,以及对可扩展性有用的额外检测手段。
在一本书中涵盖所有与并发相关的主题是不可能的,还有很多领域未被探讨。然而,我相信,一旦你研究完书中的示例,在使用并发解决问题时,你会更有信心。大家都说并发编程很难,但正确使用这门语言会让编写正确的程序变得更容易。你要始终牢记一个经验法则:正确性优先于性能。所以,先确保程序能正确运行,然后再考虑提高运行速度。
本文为《Effective Concurrency in Go》的译本,首发于 cppguide.cn (opens new window)。
限于水平有限,如果您在阅读过程中有任何问题,可以联系小方(微信cppxiaofang),也欢迎加入小方的 技术交流群,群里面有很多技术高手,不定期发布招聘信息,加群请备注“加微信群”。
小方微信公众号【CppGuide】:
# 适合读者
如果你是一名对Go语言有基础知识,并且希望在高并发后端应用开发领域获得专业知识的开发者,那么本书很适合你。本书也适合不同经验水平的Go语言开发者,帮助他们让后端系统更加健壮和可扩展。
# 目录
前言
- 并发——高级概述
- 技术要求
- 并发与并行
- 共享内存与消息传递
- 原子性、竞态条件、死锁和饥饿
- 总结
- 问题
- 延伸阅读
- Go语言并发原语
- 技术要求
- 协程(Goroutines)
- 通道(Channels)
- 互斥锁(Mutex)
- 等待组(Wait groups)
- 条件变量(Condition variables)
- 总结
- 问题
- Go语言内存模型
- 为什么需要内存模型
- 内存操作之间的先行发生(happened-before)关系
- Go语言并发原语的同步特性
- 包初始化
- 协程
- 通道
- 互斥锁
- 原子内存操作
- 映射(Map)、一次性初始化(Once)和等待组
- 总结
- 延伸阅读
- 一些著名的并发问题
- 技术要求
- 生产者-消费者问题
- 哲学家就餐问题
- 速率限制
- 总结
- 工作池(Worker Pools)和管道(Pipelines)
- 技术要求
- 工作池
- 管道、扇出和扇入
- 异步管道
- 扇出/扇入
- 有序扇入
- 总结
- 问题
- 错误处理
- 错误处理
- 流水线
- 服务器
- 恐慌(Panics)
- 总结
- 定时器和ticker(Tickers)
- 技术要求
- 定时器——稍后执行任务
- ticker——定期执行任务
- 心跳
- 总结
- 并发处理请求
- 技术要求
- 上下文、取消和超时
- 后端服务
- 分配工作和收集结果
- 信号量——限制并发数
- 流数据
- 处理多个流
- 总结
- 原子内存操作
- 技术要求
- 内存保证
- 比较并交换
- 原子操作的实际应用
- 计数器
- 心跳和进度指示器
- 取消操作
- 检测变化
- 总结
- 排查并发问题
- 技术要求
- 读取堆栈跟踪信息
- 检测故障并修复
- 调试异常
- 总结
- 延伸阅读