gogoroutine


  • 无法有效的并发执行完成


  • 无法有效的控制并发


首先我们再来看看下面这个栗子,代码如下


image.gif

此时你会发现有些任务被多次执行了,但有些任务却又没有被执行。以上例子虽加速了运行,但带来的损失却也是巨大的。例如银行转账等,一旦出现以上情况多次付款也随之而来了。弊大于利


首先我们来分析以上代码,为什么会出现此种情况?虽然是个废品,但也是俺辛辛苦苦的写的不是,让俺做个明白鬼。


image.png


anonymous1i

goroutine,执行逻辑,返回结果。


请思考:


goroutine,越多越好么?为什么


如何避免以上情景?如何避免提前退出?


信道的英文是channel,在golang当中的关键字是chan。它的用途是用来在goroutine之间传输数据,这里你可能要问了,为什么一定得是goroutine之间传输数据呢,函数之间传递不行吗?


因为正常的传输数据直接以参数的形式传递就可以了,只有在并发场景当中,多个线程彼此隔离的情况下,才需要一个特殊的结构传输数据。


CSP(Communicating Sequential Processes)


goroutinechannelchannelgoroutinegoroutine


Go 语言中的通道(channel)是一种特殊的类型。通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型。


channel底层的实现为互斥锁


example



无缓冲channel


示例代码如下



image.png


这速度可谓是非常的快啊


带缓冲Channel


带缓冲的 channel(buffered channel) 是一种在被接收前能存储一个或者多个值的通道。这种类型的通道并不强制要求 goroutine 之间必须同时完成发送和接收。通道会阻塞发送和接收动作的条件也会不同。只有在通道中没有要接收的值时,接收动作才会阻塞。只有在通道没有可用缓冲区容纳被发送的值时,发送动作才会阻塞。这导致有缓冲的通道和无缓冲的通道之间的一个很大的不同:


无缓冲的通道保证进行发送和接收的 goroutine 会在同一时间进行数据交换;有缓冲的通道没有这种保证


来段代码压压惊



运行效果如下

image.gif

image


这速度杠杠滴哈,别急,同时也让我和你说执行流程,老规矩,上图


image.png


首先开始执行把需要传递的数据打到channle里面,然后goroutine去取,执行。那么有留下几个问题


还可以加速么?


加速的方法?


可能带来什么新的问题?


如何解决?

单向 channel

有时候,我们有一些特殊的业务需求,比如限制一个 channel 只可以接收但是不能发送,或者限制一个 channel 只能发送但不能接收,这种 channel 称为单向 channel。

单向 channel 的声明也很简单,只需要在声明的时候带上 <- 操作符即可,如下面的代码所示:



使用单向 channel 的较多场景一般在函数参数中使用较多,这样可以防止一些操作影响了 channel。



小技巧:箭头该谁指谁?这可把我整的不好了,别慌,我告诉你,到底该谁指谁。其实很简单


箭头一致向左指



Chan其实就是起到一个中间人的作用,箭头指向chan,那就是放入,chan指出去 就是拿出来。


相信你应该记住了吧,反正我记住了


多路复用Channel


假设要从网上下载一个文件,启动了 5个 goroutine 进行下载,并把结果发送到 5 个 channel 中。其中,哪个先下载好,就会使用哪个 channel 的结果。


在这种情况下,如果我们尝试获取第一个 channel 的结果,程序就会被阻塞,无法获取剩下4个 channel 的结果,也无法判断哪个先下载好。这个时候就需要用到多路复用操作了,在 Go 语言中,通过 select 语句可以实现多路复用,其语句格式如下:



整体结构和 switch 非常像,都有 case 和 default,只不过 select 的 case 是一个个可以操作的 channel。


selectcaseselectcaseselect{}


channle


sync.waitGroup


goroutine

示例代码如下



640.jpg


goroutinegoroutine
sync.WaitGroup