Goroutine 与 Channel: 锁之外的另一种同步机制
在主流的编程语言中为了保证多线程之间共享数据安全性和一致性,都会提供一套基本的同步工具集,如锁,条件变量,原子操作等等。Go 语言标准库也毫不意外的提供了这些同步机制,使用方式也和其他语言也差不多。
除了这些基本的同步手段,Go 语言还提供了一种新的同步机制: Channel,它在 Go 语言中是一个像 int, float32 等的基本类型,一个 channel 可以认为是一个能够在多个 Goroutine 之间传递某一类型的数据的管道。Go 中的 channel 无论是实现机制还是使用场景都和 Java 中的 BlockingQueue 很接近。
1 | // 声明channel变量 |
几乎等价于的 Java 中的操作:
1 | TransferQueue<Integer> syncQueue = new LinkedTransferQueue<Integer>(); |
a. 与 Java 的 BlockingQueue 一样用在需要生产者消费者模型的并发环境中。
b. 锁同步场景下一种替代方案。在 Go 的并发编程中有一句很经典的话:不要以共享内存的方式去通信,而要以通信的方式去共享内存。在 Go 语言中并不鼓励用锁保护共享状态的方式在不同的 Goroutine 中分享信息(以共享内存的方式去通信)。而是鼓励通过 channel 将共享状态或共享状态的变化在各个 Goroutine 之间传递(以通信的方式去共享内存),这样同样能像用锁一样保证在同一的时间只有一个 Goroutine 访问共享状态。但这的确需要转换以前用锁做并发同步的思维方式,大家觉得那种适合自己和自己的使用场景就用哪种好了,并不能很简单、绝对地说哪种方式更好,更高效。