在 Go 中使用 Channel 保证并发安全,意味着:读与写必须在同一个协程中进行
如果无法保证到在同一个协程中进行,就必须新建一个协程来完成这件事;否则就不能用协程,只能用其它手段,如锁
倘若需要新建一个协程来实现并发安全,那么就必须保证在开始并发读写前,完成对相关 Channel 的监听,这就必然会引申出形如
使用 Channel 来实现并发安全,至少需要 3 个 Channels。一是接收写操作命令,并完成写操作;二是接收读操作命令,读取数据,传递到第三个 Channel 返回给调用方。这是由于 Go 的类型系统比较简单,第一个 Channel 类型是
接收写操作命令的 Channel 与接收读操作命令的 Channel,它们本质上都是用来接收,那么两者可以合并成一个吗?
可以,但不必要。
首先,由于两者接收的数据最终目的不同,这就要求有一个 interface 作为接收这个操作的统一类型,这需要写更多的代码来表示读与写具体操作实现;然而,这不是重点
其次,每次需要读或写操作时,我们都需要新建一个操作实例发送到 Channel;然而,当我们谈及并发安全时,意味着读写是相当高频的操作,进一步,在垃圾回收前,将会产生大量的废弃对象。而相比于直接使用 3 个 Channels,最后也只需回收 3 个对象
当然,读写操作实例,我们可以复用;但复用也意味着我们需要对这些对象进行维护;而当操作不止是读或写两种操作时,是可以根据情况考虑
综上,可以在开始时无脑使用 3 个 Channels
如果无法保证到在同一个协程中进行,就必须新建一个协程来完成这件事;否则就不能用协程,只能用其它手段,如锁
倘若需要新建一个协程来实现并发安全,那么就必须保证在开始并发读写前,完成对相关 Channel 的监听,这就必然会引申出形如
Start 之类的调用使用 Channel 来实现并发安全,至少需要 3 个 Channels。一是接收写操作命令,并完成写操作;二是接收读操作命令,读取数据,传递到第三个 Channel 返回给调用方。这是由于 Go 的类型系统比较简单,第一个 Channel 类型是
chan <data type>`;第二个 Channel 类型一般是 `chan structure{}`;第三个 Channel 类型是 `chan <data type>接收写操作命令的 Channel 与接收读操作命令的 Channel,它们本质上都是用来接收,那么两者可以合并成一个吗?
可以,但不必要。
首先,由于两者接收的数据最终目的不同,这就要求有一个 interface 作为接收这个操作的统一类型,这需要写更多的代码来表示读与写具体操作实现;然而,这不是重点
其次,每次需要读或写操作时,我们都需要新建一个操作实例发送到 Channel;然而,当我们谈及并发安全时,意味着读写是相当高频的操作,进一步,在垃圾回收前,将会产生大量的废弃对象。而相比于直接使用 3 个 Channels,最后也只需回收 3 个对象
当然,读写操作实例,我们可以复用;但复用也意味着我们需要对这些对象进行维护;而当操作不止是读或写两种操作时,是可以根据情况考虑
综上,可以在开始时无脑使用 3 个 Channels