语言表达了我们的思维方式。我们如何处理问题并制定解决方案取决于我们可以使用语言表达的概念。这对于编程语言也是如此。给定一个问题,为解决该问题而编写的程序可能因为语言的不同而有较大的差异。本书讲述的是如何用Go语言来表达并发算法并编写程序,以及如何了解这些程序的行为方式。
Go语言与许多流行语言的不同之处在于它强调可理解性。这与可读性不同。许多用易于阅读的语言编写的程序是难以理解的。过去,我也曾陷入使用使编程变得容易的框架来编写组织良好的程序的陷阱。这种方法的问题在于,一旦编写完成,程序就开始了自己的生命周期,而其他人则接管了它的维护工作。在开发阶段形成的专有知识丢失了,如果没有原始开发团队中最后一个人的帮助,那么团队留下的程序将无法理解。开发程序与写小说没有太大区别。小说是为了让别人读而写的,程序也是如此。你的程序如果没有人能理解,那么肯定无法长期运行。
本书将尝试解释如何在Go语言中使用并发结构进行思考,以便你在获得一段代码时能够清晰地理解该程序将如何运行,并且其他人也可以更轻松地理解你编写的程序。本书首先对并发以及Go语言的处理方式进行较高层次上的阐释,然后使用并发算法解决若干个实用的数据处理问题。毕竟,编写程序就是为了处理数据。本书希望你理解并发模式是如何在解决现实问题的同时全面发展的,这可以帮助你获得高效使用该语言的技能。本书后面的章节还介绍更多示例,这些示例涉及计时、周期性任务、服务器编程、流媒体和原子内存操作等。最后一章则讨论故障排除和调试等。
限于篇幅,本书无法讨论与并发相关的所有主题。还有很多领域没有被探索。但是我相信,你一旦完成了本书中提供的所有示例,就会对使用并发解决问题更有信心。每个人都在抱怨并发很难,但是,正确使用语言将使开发人员可以更轻松地生成正确的程序。你应该永远记住的经验法则是:正确性优先于性能。因此,我们首先要让它正常工作,然后才能让它更快地工作。
本书读者
如果你是一名具有Go语言基础知识并希望获得高并发后端应用程序开发专业知识的开发人员,那么这本书就是适合你的。本书还将吸引各种经验水平的Go开发人员,让他们的后端系统更加健壮和可扩展。
内容介绍
本书共分10章,各章内容如下。
第1章并发高级概述,详细阐述并发是什么以及不是什么,特别是它与并行的关系。本章还介绍共享内存和消息传递范式,以及常见的并发概念,如竞争、原子性、死锁和饥饿等。
第2章Go并发原语,介绍用于并发编程的Go语言原语,包括goroutine、通道、互斥体、等待组和条件变量等。
第3章Go内存模型,详细探讨内存操作的可见性保证,介绍happened-before关系,这允许你推理并发行为。本章还讨论并发原语和一些标准库函数的内存可见性保证。
第4章一些众所周知的并发问题,研究著名的生产者/消费者问题、哲学家就餐问题和速率限制算法。
第5章工作池和管道,详细介绍工作池的机制,这是在有限并发下处理大量数据的常用方法。本章还演示多种并发数据管道实现,以帮助你编写高效的数据处理应用程序。
第6章错误和恐慌处理,深入探讨如何处理并发程序中的错误和恐慌,以及如何传递错误。
第7章Timer和Ticker,介绍一次性定时器Timer和周期性定时器Ticker。 Timer用于稍后运行一些东西,而Ticker则可用于定期运行一些东西。
第8章并发处理请求,主要讨论服务器编程。本章讨论的许多概念涉及处理多种请求,因此它们可以广泛应用于各种场景。本章描述如何有效地使用上下文、如何分配工作和收集结果、如何限制并发以及如何流传输数据。
第9章原子内存操作,详细阐释原子内存操作和它们的内存保证,并演示原子的一些实际用途。
第10章解决并发问题,讨论读取堆栈跟踪信息这一被低估但必不可少的技能,以及如何在运行时检测故障并修复它们。
充分利用本书
你需要对Go语言以及适合你的操作系统运行的Go开发环境有基本的了解。本书不依赖任何第三方工具或库,你只需使用你最熟悉的代码编辑器即可。所有示例和代码示例都可以使用Go构建系统进行构建和运行。
下载示例代码文件
本书的代码包已经托管在GitHub上,其网址如下:
https://github.com/PacktPublishing/Effective-Concurrency-in-Go
代码如果有更新,则会在现有GitHub存储库上被更新。
下载彩色图像
我们还提供了一个PDF文件,其中包含本书中使用的屏幕截图/图表的彩色图像。你可以访问以下网址下载该文件:
https://packt.link/3rxJ9
本书约定
本书中使用了许多文本约定。
(1)代码格式文本:表示文本中的代码字、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟URL、用户输入和Twitter句柄等。以下段落就是一个示例:
本章源代码可在本书配套的GitHub存储库中找到,其网址如下:
https://github.com/PacktPublishing/Effective-Concurrency-in-Go/tree/main/chapter4
(2)有关代码块的设置如下所示:
1: chn := make(chan bool) // 创建一个无缓冲通道
2: go func() {
3: chn <- true // 发送到通道
4: }()
5: go func() {
6: var y bool
7: y <-chn // 从通道接收
8: fmt.Println(y)
9: }()
(3)任何命令行输入或输出都是采用如下形式编写的:
{"row":65,"height":172.72,"weight":97.61}
{"row":64,"height":195.58,"weight":81.266}
{"row":66,"height":142.24,"weight":101.242}
{"row":68,"height":152.4,"weight":80.358}
{"row":67,"height":162.56,"weight":104.87400000000001}
(4)术语或重要单词采用中英文对照形式给出,括号内保留其英文原文,方便读者进行对照和查看。示例如下:
多年来,人们已经开发出了若干种数学模型来分析和验证并发系统的行为。通信顺序进程(communicating sequential processes,CSP)就是影响Go语言设计的模型之一。在CSP中,系统由多个并行运行的顺序进程组成。
(5)本书还使用了以下两个图标。
表示警告或重要的注意事项。
表示提示信息或操作技巧。