失效链接处理 |
Concurrency in Go 中文笔记 PDF 下载
本站整理下载:
相关截图:
主要内容:
数据竞争
当两个或更多的操作必须以正确的顺序执行时,就会出现竞争状态,但如果程序没有写入,无法使操作顺序得到保持。
大多数时候,这出现在所谓的数据竞争中,其中一个并发操作尝试在某些未确定的时间读取变量,而另一个并发操作尝试写入
同一个变量。
这里有一个简单的例子:
1. 在Go中,可以使用go关键字同时运行一个函数。 这样做创建了所谓的goroutine。
在第3行和第5行都试图访问名为data的变量,但是并没有施行任何措施保证执行的顺序。运行此代码有三种可能的结果:
没有输出。在这种情况下,第3行是在第5行之前执行的。
输出 the value is 0。在这种情况下,第5行和第6行在第3行之前执行。
输出 the value is 1。在这种情况下,第5行在第3行之前执行,但第3行在第6行之前执行。
正如你所看到的,仅仅几行不确定的代码会在你的程序中引入巨大的变化。
大多数情况下,数据竞争是由于开发人员按顺序思考问题而引入的。 他们认为,上一行代码会先于下一行代码执行。 他们假设
在if语句中读取数据变量之前,上面的goroutine将被调度并执行。
在编写并发代码时,你必须仔细地遍历所有可能出现的场景。 除非你正在使用本书稍后部分介绍的一些技巧,否则保证代码将
按其在源代码中列出的顺序运行。 我有时会发现在操作之间等待很长一段时间会很有帮助。 想象一下,在调用goroutine的时
间和运行的时间之间要经过一个小时。 该程序的其余部分如何运作? 如果在goroutine成功执行和程序到达if语句之间花了一
个小时呢? 以这种方式思考对我有所帮助,因为对于计算机而言,规模可能不同,但相对时间差异差不多。
事实上一些开发者确实这么干并发现看起来解决了并发上的问题,我们修改上个例子看看:
我们解决了数据竞争问题吗吗?没有。事实上,从这个方案中产生的所有三个结果仍然是可能的。我们在调用我们的goroutine
和检查数据值之间的让程序休眠的时间越长,程序越接近实现正确性——但这只是在概率上渐近地接近逻辑正确而已。
除此之外,这样做已经在算法中引入了低效率。 程序现在必须休眠一秒钟才能使我们更有可能看不到的数据竞争。如果我们使
用正确的方式来编写代码,我们可能无需等待,或者等待时间可能只有1微秒。
这里要说的是,你应该总是以逻辑的正确性为目标。 在你的代码中引入休眠可以是一种调试并发程序的方便方式,但不是解决
方案。
|