面对一个并发问题,我们的解决方案是使用channel还是互斥锁来实现并不总是很清晰。因为Go提倡使用通信来共享内存,所以一个常见的错误就是总是强制使用channel,不管实际情况如何。但是我们应该把这两种选择作为互补手段。
首先,简单回顾一下Go语言中的channel:channel是一种交流机制。在内部,channel是用来发送和接收值的管道,它允许我们连接并发的goroutine。channel的类型可以是下面两种的一种:
- unbuffered--发送者的goroutine一直阻塞,直到接收者的goroutine准备好接收。
- buffered当缓冲区满了时,发送者的goroutine阻塞
那么我们什么时候用channel,什么时候使用互斥锁?我们使用下图的例子做为基础。该例中包含三个具有特定关系的不同的goroutine:
- G1和G2是并行的goroutine。它们是两个执行相同函数的goroutine,不断地从channel中接收数据,或者两个goroutine同时执行相同的HTTP处理程序。
- 另外,G1和G3是并发的goroutine,G2和G3也是并发的goroutine。所有的goroutine都是整体并发结构的一部分,但G1和G2执行第一步,而G3执行下一步。</