持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
🎐 放在前面说的话
大家好,我是北 👧🏻
本科在读,此为日常捣鼓.
如有不对,请多指教,也欢迎大家来跟我讨论鸭 👏👏👏
今天是我们「Go并发」系列的第一篇:「轻量级线程选手goroutine」;
Let’s get it
一、goroutine
1. goroutine概念
- Go通过关键词
go来创建goroutine实现并发。 - goroutine类似线程,属于用户态的轻量级线程,可以创建成千上万个goroutine进行并发工作,故先后执行顺序不确定(goroutine是由Go语言的运行时调度完成,线程时由操作系统调度完成)
2. goroutine优势
- 可增长的分段线堆,即它们在调用时,才会占用更多的内存
- 启动时间比线程快
- 原生支持
channel安全进行通信
二.goroutine的使用
在调用函数时,在函数前加上
go关键词即可.一个函数可以被创建多个 goroutine,一个 goroutine 必定对应一个函数。
1)格式
普通创建:
go 函数名(参数)
或者用匿名函数创建:
go func(形参){ 函数体 }(实参)
go创建goroutine时,会忽略被调用函数的返回值.若需要在goroutine中返回数据,可用channel实现,下一篇会说明.
2)启动单个goroutine试试鲜
func hello(){
fmt.Println("Hello goroutine!")
}
func main(){
hello()
fmt.Println("main goroutine done!")
}
执行打印:
现在,我们在原基础上尝试一下,在main主函数里再起一个goroutine
func test() {
fmt.Println("Hello goroutine!")
}
func main() {
go hello()
fmt.Println("main goroutine done!")
}
这次只打印了:
为什么?
因为在程序启动时,Go程序会为main()函数创建一个默认的goroutine。当main()函数返回的时候,默认的goroutine就结束了,在main函数中启动的goroutine也一并结束。它如同一个主宰,它亡,子民也要跟随它而去。
怎么解决?
让main()函数里的goroutine等一等,可用time.sleep或WaitGroup:
var wg sync.WaitGroup
func hello() {
fmt.Println("Hello goroutine!")
wg.Done() // 通知wg把计数器-1
}
func main() {
wg.Add(1) // 计数器+1
go hello()
fmt.Println("main goroutine done!")
//time.Sleep(time.Second * 1)
wg.Wait() // 等待所有goroutine结束,main()函数主线程再结束
}
3)启动多个goroutine试试鲜
//创建等待组
var wg sync.WaitGroup
func hello(i int) {
fmt.Printf("hello goroutine %d\n", i)
wg.Done() // 通知wg把计数器-1
}
//程序启动时会创建一个名为main的goroutine去执行
func main() {
// for循环,创建3个goroutine
for i := 0; i < 3; i++ {
wg.Add(1) // 计数器+1
go hello(i) // 开启一个单独的Goroutine去执行当前函数
}
fmt.Println("main goroutine")
wg.Wait() // 等待所有goroutine结束,main()函数主线程再结束
}
执行打印:
以上用到的WaitGroup,我们会再出一篇关于并发编程中sync包的使用
📖一些概念科普
并发&并行
-
并发:同一时间内执行多个任务(我在vx上和两个朋友聊天)
-
并行:同一时刻执行多个任务 (我和我朋友都在vx上和朋友聊天)
进程&线程&协程
-
进程:程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位 (进程是车间,车间里必须有一个或以上的工人)
-
线程:线程是进程的一个执行实体,是 CPU 调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。一个线程上可以跑多个协程,协程是轻量级的线程。 (线程是车间里自由行动的工人)
-
协程:独立的栈空间,共享堆空间,调度由用户自己控制,本质上有点类似于用户级线程,这些用户级线程的调度也是自己实现的。 (工人手上的工具)
-
CPU:中央处理器,计算机系统的运算和控制核心,是信息处理、程序运行的最终执行单元。 (CPU是一个含有很多很多的车间大工厂)
🎉 放在后面的话
Go语言作为新兴的语言,最近发展势头也很是迅猛,其最大的特点就是原生支持并发。它使用的是goroutine模型.goroutine 是 Go 语言内建的语言特性,它使用了一个称为协程的概念、易于使用,并且性能较高.Go 运行时调度器可将goroutine复用到其他线程上,当下线程阻塞时,Go 运行时将阻塞的 goroutine移动到另一个可运行的内核线程,提高工作效率。goroutine还原生支持很多工具,例如goroutines之间安全通信的 channel。如果大家需要开发高并发的应用程序或者服务等,Go是一个很不错的选择.