内容简介:本文完,获取更多资讯,敬请关注区块链工程师。
原文链接: 区块链技术语言(二十七):Go语言并发编程(上)
并发编程分为上、下两节。这一节包括了并发编程的概述、goroutine和channel的部分内容。
1 概述
1.1 并行和并发
并行(parallel):在多个处理器上同时执行多条指令,如图1所示。
并发(concurrency):同一时刻只有一条指令在执行,但多个进程指令被快速轮换地执行,使得宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的。它只是把这段时间进行划分、快速交替地执行,如图2所示。
1.2 Go 语言并发优势
Go语言原生支持并发。
首先,虽然一个并发程序内存管理复杂,但Go语言提供了自动垃圾回收机制,可以自动判断何时需要释放内存,并在CPU相对空闲的时候对不使用的内存进行收集。
其次,Go语言提供了goroutine。goroutine即一个函数或方法,它仅需4~5KB的内存,所以创建一个goroutine代价极小。另外,Go语言存在一个内置的数据结构——通道(channel),它能够让不同的goroutine之间同步安全地发送消息。因此,Go语言让并发编程变得更加轻盈和安全。
因此,一个运行的程序可以创建成百上千个goroutine,充分利用计算机资源,自动管理内存,实现了高并发。
2 goroutine
2.1 goroutine的定义
关于goroutine,Go语言之父Rob Pike说:“一个goroutine是一个与其它goroutines并发运行在同一地址空间的Go函数或方法。一个运行的程序由一个或更多个goroutine组成。它与线程、协程、进程等不同,它是一个goroutine。”
所以我们可以认为goroutine就是一个函数或方法。
2.2 goroutine的创建和运行
在函数或者方法的调用语句之前添加关键字go,就可以创建一个goroutine。开发人员无需了解任何执行细节,调度器会自动将其安排到合适的系统线程上执行。
当一个程序启动时,其主函数在一个单独的goroutine中运行,这个goroutine叫作main goroutine。新的goroutine用go语句来创建。
2.2.1 main goroutine
在Go语言里,主函数运行在main goroutine中,其它goroutines和main goroutine并发运行。如果main goroutine先执行完毕,那么其它的goroutines也会自动退出。
2.2.2 其它goroutines
如果要运行所有其它的goroutines,main goroutine必须继续在运行,直到其它goroutines运行完毕。
2.3 runtime包
2.3.1 Gosched
runtime.Gosched() 用于让出当前goroutine的执行权限,调度器安排其他等待的任务运行,并在下次某个时候从该位置恢复执行。
2.3.2 Goexit
调用runtime.Goexit(),会立即终止当前goroutine的执行,调度器确保所有已注册defer延迟调用被执行。
2.3.3 GOMAXPROCS
调用runtime.GOMAXPROCS() 用来设置可以并行计算的CPU核数的最大值,并且返回设置之前用于并行计算的CPU核数最大值。
3 channel
在Go语言里,各个goroutine运行在相同的地址空间,因此访问共享内存必须做好同步。
当一个资源需要在两个goroutine之间共享,channel在两个goroutine之间架起一个管道,并提供了确保同步交换数据的机制。可以通过channel共享内置类型、命名类型、结构类型和引用类型的值或指针。
channel是基于底层数据结构的引用,当我们复制一个channel或用于函数参数传递时,我们只是拷贝了一个channel引用。和其它的引用类型一样,channel的零值也是nil。
3.1 channel的创建
在Go语言中,通过内置函数make可以创建一个channel,需要定义发送到channel的值的类型。其创建格式如下:
注:a. 当capacity=0时,channel是无缓冲阻塞读写的;
b. 当capacity>0时,channel有缓冲、非阻塞的,直到写满capacity个元素才阻塞写入。
3.2 channel中的数据发送和接收
channel通过操作符<-来接收和发送数据,发送和接收数据的语法格式如表1所示。默认情况下,channel接收和发送数据都是阻塞的,除非另一端已经准备好。
3.3 无缓冲的channel
3.3.1 概述
无缓冲的通道(unbuffered channel)是指在接收前没有能力保存任何值的通道。这种类型的通道要求同时准备好发送goroutine和接收goroutine,才能完成发送和接收操作。如果两个goroutine没有同时准备好,通道会导致先执行发送或接收操作的goroutine阻塞等待。这种对通道进行发送和接收的交互行为本身就是同步的,其中任意一个操作都无法离开另一个操作单独存在。
图1通过示意图分析了两个goroutine利用无缓冲通道共享一个值:
a. 第1步,两个goroutine都到达通道两端,但两个都没有开始执行发送数据或者接收数据;
b. 第2步,左侧的goroutine将它的手伸进通道,这模拟了向通道发送数据的行为。此时,这个goroutine会在通道中被锁住,直到交换完成;
c. 第3步,右侧的goroutine将它的手放入通道,这模拟了从通道里接收数据。这个goroutine也一样会在通道中被锁住,直到交换完成;
d. 第4步和第5步,进行数据交换;
e. 第6步,两个goroutine都将它们的手从通道里拿出来,这模拟了被锁住的goroutine得到释放。两个goroutine现在都可以去做别的事情了。
3.3.2 无缓冲channel的创建
无缓冲channel没有指定缓冲区容量,那么在无缓冲的channel中,数据发送和接收同步,其创建格式如下:
示例如下:
3.3.3 内置函数close在channel中的应用
如果发送者知道没有更多的值发送到channel,那么让接收者也能及时知道没有多余的值可接收将是有用的。因为接收者可以停止不必要的接收等待,这可以通过内置的close函数来实现channel的关闭。
channel不像文件一样需要经常关闭,只有确实没有任何数据发送到channel,才关闭channel;关闭channel后,无法向channel再发送数据;对于nil channel,无论收发都会被阻塞。
3.3.4 用range接收channel中的数据
关键词range结合for循环可用于在一个channel关闭之前,从channel中接收数据。如果要结束此操作,用close函数关闭channel。
参考资料:
https://www.cnblogs.com/tangchuanyang/p/5553434.html
http://www.flysnow.org/2017/04/11/go-in-action-go-goroutine.html
https://studygolang.com/articles/3028
本文完,获取更多资讯,敬请关注区块链工程师。
来源:链块学院
本文由布洛克专栏作者发布,代表作者观点,版权归作者所有,不代表布洛克科技观点
——TheEnd——
关注“布洛克科技”
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 区块链技术语言(十五):Go语言指针
- 区块链技术语言(十九):Go语言字典
- 区块链技术语言:Go语言选择语句 | 十
- 区块链基础语言(二十)——Go语言结构体
- 区块链技术语言(二十一)——Go语言包
- 区块链技术语言(二十六):Go语言字典
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java Web开发从初学到精通
方振宇 / 电子工业 / 2010-6 / 69.00元
《Java Web开发从初学到精通》介绍如何整合Web框架进行J2EE开发,所有实例都基于MyEclipse IDE开发,引领读者快速进入基于JaVa web的J2EE应用领域。《Java Web开发从初学到精通》开始主要介绍Servlet、JSP、JavaBean、EL、JSTL、JDBC等Web开发基础知识,然后学习Struts、Hibernate、Spring、Ajax、JSF等开源框架,并......一起来看看 《Java Web开发从初学到精通》 这本书的介绍吧!