This commit is contained in:
Xargin
2016-09-30 21:56:19 +08:00
parent 25eec00705
commit 853e2ad052
6 changed files with 10 additions and 10 deletions

View File

@@ -51,7 +51,7 @@ fmt.Println(<-ch) // "B"
fmt.Println(<-ch) // "C"
```
在这个例子中发送和接收操作都发生在同一个goroutine中但是在真的程序中它们一般由不同的goroutine执行。Go语言新手有时候会将一个带缓存的channel当作同一个goroutine中的队列使用虽然语法看似简单但实际上这是一个错误。Channel和goroutine的调度器机制是紧密相连的一个发送操作——或许是整个程序——可能会永远阻塞。如果你只是需要一个简单的队列使用slice就可以了。
在这个例子中发送和接收操作都发生在同一个goroutine中但是在真的程序中它们一般由不同的goroutine执行。Go语言新手有时候会将一个带缓存的channel当作同一个goroutine中的队列使用虽然语法看似简单但实际上这是一个错误。Channel和goroutine的调度器机制是紧密相连的一个发送操作——或许是整个程序——可能会永远阻塞。如果你只是需要一个简单的队列使用slice就可以了。
下面的例子展示了一个使用了带缓存channel的应用。它并发地向三个镜像站点发出请求三个镜像站点分散在不同的地理位置。它们分别将收到的响应发送到带缓存channel最后接收者只接收第一个收到的响应也就是最快的那个响应。因此mirroredQuery函数可能在另外两个响应慢的镜像站点响应之前就返回了结果。顺便说一下多个goroutines并发地向同一个channel发送数据或从同一个channel接收数据都是常见的用法。
@@ -73,7 +73,7 @@ func request(hostname string) (response string) { /* ... */ }
Channel的缓存也可能影响程序的性能。想象一家蛋糕店有三个厨师一个烘焙一个上糖衣还有一个将每个蛋糕传递到它下一个厨师在生产线。在狭小的厨房空间环境每个厨师在完成蛋糕后必须等待下一个厨师已经准备好接受它这类似于在一个无缓存的channel上进行沟通。
如果在每个厨师之间有一个放置一个蛋糕的额外空间那么每个厨师就可以将一个完成的蛋糕临时放在那里而马上进入下一个蛋糕在制作中这类似于将channel的缓存队列的容量设置为1。只要每个厨师的平均工作效率相近那么其中大部分的传输工作将是迅速的个体之间细小的效率差异将在交接过程中弥补。如果厨师之间有更大的额外空间——也是就更大容量的缓存队列——将可以在不停止生产线的前提下消除更大的效率波动例如一个厨师可以短暂地休息然后加快赶上进度而不影响其他人。
如果在每个厨师之间有一个放置一个蛋糕的额外空间那么每个厨师就可以将一个完成的蛋糕临时放在那里而马上进入下一个蛋糕在制作中这类似于将channel的缓存队列的容量设置为1。只要每个厨师的平均工作效率相近那么其中大部分的传输工作将是迅速的个体之间细小的效率差异将在交接过程中弥补。如果厨师之间有更大的额外空间——也是就更大容量的缓存队列——将可以在不停止生产线的前提下消除更大的效率波动例如一个厨师可以短暂地休息然后加快赶上进度而不影响其他人。
另一方面,如果生产线的前期阶段一直快于后续阶段,那么它们之间的缓存在大部分时间都将是满的。相反,如果后续阶段比前期阶段更快,那么它们之间的缓存在大部分时间都将是空的。对于这类场景,额外的缓存并没有带来任何好处。