学习golang(10) 初探:协程(1)

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情

这里卡了好久,是因为 进程、线程以及协程 的关系较为难以用文字表达出来。

什么是协程

要弄清楚什么是协程,我们需要先了解下进程 和 线程 之间的关系,我们从内存的角度来看待该问题,我们都知道,进程是操作系统进行资源分配和调度的基本单位。 并且其程序虚拟内存分布图大致如下

线程是操作系统能够进行调度的最小单位,一个进程至少有一个线程,在上述虚拟内存分布图中,线程会在栈区分配一块区域来存放数据,其他资源则和其他线程共享,例如: 代码段、数据段 以及 堆,其虚拟内存分布大致如下

协程,也称之为用户态线程或则说轻量级线程,顾名思义,协程是在用户态中自己维护的,系统调用则是通过线程去调用的。这样好处为对于内存而言,申请协程,比申请线程内存开销要小得多。

go 协程

开启协程

golang中,使用关键字go开启协程,例如

我们执行程序后,输出为

go中,我们通常将main函数称之为主协程,在主协程中调用其他协程序,我们协程给的次数是100(go worker("斜程处理中",100)),值得注意的是,当主协程执行完毕后,其他协程也给关闭了,我们可以将执行过程整理图示如下:

那么,我们是否有方法等待协程结束呢? 有的

等待协程执行完毕

我们可以使用sync.WaitGroup来等待协程执行完毕后再执行下面的语句,其方法名和具体含义为

  • (wg *WaitGroup) Add(delta int)

delta增加到waitgroup计数器,该值可能为负数

  • func (wg *WaitGroup) Done()

等同于 (wg *WaitGroup) Add(-1)

  • func (wg *WaitGroup) Wait()

会持续等待,直至waitgroup计数器为0

我们来写一个等待协程执行完毕的例子

这里有个点,我们为什么将wg.Add(1)放到匿名函数之外呢,如果我们放到匿名函数里面,协程压根就不会跑就结束了。

我们执行下

协程序小案例

具体代码参见: gitee.com/pdudo/golea…

我们早些时候学习shell的时候,写过多进程拷贝文件且打包的案例,这里将shell代码贴过来一下

其具体逻辑为:

我们重新用go协程来写一下,这里贴一下用协程拷贝文件的代码

具体的可以查看详细代码

总结

我们今天了解了什么是进程、线程 和 协程序(我现在还是晕晕乎乎的),除此之外,我们还了解了go协程,我们可以将main函数看做一个主协程,在主协程中开启其他协程,当主协程执行完毕后,会结束其他协程执行,以及sync.WaitGroup 计数器,最后我们通过一个拷贝案例来逐步了解go协程应用。

posted @ 2022-06-04 22:30  pdudos  阅读(0)  评论(0编辑  收藏  举报  来源