1.Go语言特点

Go是一种静态强类型的开源语言,诞生于2009年,是非常年轻的一门语言其主要目标时“兼具Python等动态语言的开发速度,同时又具备想C语言C++的安全性与应能”,其中最大的特点(优势)就是并发编程

不同于大多编程语言的多线程,golang的并发执行单元是一种称之为goroutine的携程,由于绝大部分语言在其共享数据时会用到并发锁,再加上GC,其执行效率多多少少会受到影响,golang的并发编程简单。

  1. channel的使用——并发编程

这种是无缓冲的channel,一旦goroutine向管道内发送数据,那么当前的goroutine会被阻塞,直到其他的携程消费了管道里的数据才能正常运行。

这种是有缓存的管道,与上面相比增加以一个uint型参数表示缓存容量,表示可并发执行的最大数量,只要当前channel类的元素总数不大于可缓冲容量,则当前的协程就不会阻塞住。


图1.png


*注意:管道的出入方式与出弹栈有所不同,前者时先入先出而后者是先入后出(如下图)


图2.png


2.1多个goroutine协同

多个写成最后汇总至结果

其执行结果如下:

*从执行效率看go语言的并发效率要比Java和C的高出不少,在上述代码中三个go func并发执行,并且互不干涉(这里还没有涉及到互斥锁)最终输出的顺序还没有混乱。

2.2 channel底层原理

再往下深究至源码 channel返回类型hchan结构体,如下图

该结构体中详细定义了管道内的各种操作 channel再进行数据写入写出时会有缓冲设置以及无缓冲的设置其异同如下

无缓冲channel

先写再读


图3.png


由于 channel 是无缓冲的,所以 G1 暂时被挂起在队列里(由结构体中sendq字段接收),然后 G1 调用了 gopark字段 休眠了起来。接着,又有协程来channel读取数据了:

先读再写

如下图:


图4.png


此时G1被暂时性挂起,等待进入channel

G2在进入管道时发现前面有协程存在,于是给G1发讯息,等待下次被调。

如下图:


图5.png