
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
我们在前几期的文章中给大家简单介绍了go语言编程需要学习和掌握的一些编程知识等内容,而本文我们就通过案例分析来继续学习一下,go语言并发编程开发实践都有哪些。
"Go并发"这个词拆开来看,它包含两方面内容,一个是并发的概念,另一个是Go针对并发设计给出的自身的实现方案,也就是goroutine、channel、select这些Go并发的语法特性。
Go实现了goroutine这一由Go运行时(runtime)负责调度的、轻量的用户级线程,为并发程序设计提供原生支持。
并发是一种能力,它让你的程序可以由若干个代码片段组合而成,并且每个片段都是独立运行的。goroutine恰恰就是Go原生支持并发的一个具体实现。无论是Go自身运行时代码还是用户层Go代码,都无一例外地运行在goroutine中。
goroutine的执行函数的返回,就意味着goroutine退出.
如果maingoroutine退出了,那么也意味着整个应用程序的退出。如果你要获取goroutine执行后的返回值,你需要另行考虑其他方法,比如通过goroutine间的通信来实现.
调度:
将这些Goroutine按照一定算法放到“CPU”上执行的程序,就被称为Goroutine调度器(GoroutineScheduler)。Goroutine调度器的任务也就明确了:将Goroutine按照一定算法放到不同的操作系统线程中去执行.
调度原理:
P是一个“逻辑Proccessor”,每个G(Goroutine)要想真正运行起来,先需要被分配一个P,也就是进入到P的本地运行队列(localrunq)中。对于G来说,P就是运行它的“CPU”,可以说:在G的眼里只有P。但从Go调度器的视角来看,真正的“CPU”是M,只有将P和M绑定,才能让P的runq中的G真正运行起来。
Go运行时已经实现了netpoller,这使得即便G发起网络I/O操作,也不会导致M被阻塞(仅阻塞G),也就不会导致大量线程(M)被创建出来。
Channel
channel既可以用来实现Goroutine间的通信,还可以实现Goroutine间的同步。它就好比Go并发设计这门“武功”的秘籍口诀.
在理解channel的发送与接收操作时,你一定要始终牢记:channel是用于Goroutine间通信的,所以绝大多数对channel的读写都被分别放在了不同的Goroutine中。
无缓冲Channel:
由于无缓冲channel的运行时层实现不带有缓冲区,所以Goroutine对无缓冲channel的接收和发送操作是同步的。也就是说,对同一个无缓冲channel,只有对它进行接收操作的Goroutine和对它进行发送操作的Goroutine都存在的情况下,通信才能得以进行,否则单方面的操作会让对应的Goroutine陷入挂起状态.
对无缓冲channel类型的发送与接收操作,一定要放在两个不同的Goroutine中进行,否则会导致deadlock
无缓冲的Channel作用:
一种用法:用作信号传递
二种用法:用于替代锁机制(同步)
有缓冲Channel:
带缓冲channel的运行时层实现带有缓冲区,因此,对带缓冲channel的发送操作在缓冲区未满、接收操作在缓冲区非空的情况下是异步的(发送或接收不需要阻塞等待)。
对一个带缓冲channel来说,在缓冲区未满的情况下,对它进行发送操作的Goroutine并不会阻塞挂起;在缓冲区有数据的情况下,对它进行接收操作的Goroutine也不会阻塞挂起。
但当缓冲区满了的情况下,对它进行发送操作的Goroutine就会阻塞挂起;当缓冲区为空的情况下,对它进行接收操作的Goroutine也会阻塞挂起。
【免责声明】本文系本网编辑部分转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与管理员联系,我们会予以更改或删除相关文章,以保证您的权益!更多内容请加danei0707学习了解。欢迎关注“达内在线”参与分销,赚更多好礼。