这是『就要学习 Go 语言』系列的第 21 篇分享文章markdown
提到并发,相信你们还听过另外一个概念 -- 并行。我先给你们介绍下这二者之间的区别,再来说 Go 语言的并发。多线程
并行其实很好理解,就是同时执行的意思,在某一时间点可以执行多个任务。 想达到并行效果,最简单的方式就是借助多线程或多进程,这样才可在同一时刻执行多个任务。单线程是永远没法达到并行状态的。 并发是在某一时间段内能够同时处理多个任务。咱们一般会说程序是并发设计的,也就是说它容许多个任务同时执行,这个同时指的就是一段时间内。单线程中多个任务以间隔执行实现并发。 能够说,多线程或多进程是并行的基础,但单线程也经过协程实现了并发。并发
举个常见的例子,一台单核电脑能够下载、听音乐,实际上这两个任务是这样执行的,只不过这两个任务切换时间短,给人的感受是同时执行的。 函数
Go 经过协程实现并发,协程之间靠信道通讯,本篇文章先给你们介绍协程的使用,后面再写信道。oop
协程(Goroutine)能够理解成轻量级的线程,但与线程相比,它的开销很是小。所以,Go 应用程序一般能并发地运行成千上万的协程。 Go 建立一个协程很是简单,只要在方法或函数调用以前加关键字 go 便可。学习
func printHello() { fmt.Println("hello world goroutine") } func main() { go printHello() // 建立了协程 fmt.Println("main goroutine") } 复制代码
输出:spa
main goroutine
复制代码
上面代码,第 6 行使用 go 关键字建立了协程,如今有两个协程,新建立的协程和主协程。printHello() 函数将会独立于主协程并发地执行。 是的,你没有看错,程序的输出就是这样,不信?你能够实际运行下程序。你惊讶的是,printHello() 函数为何没有输出,到底发生了什么? 当协程建立完毕以后,主函数当即返回继续执行下一行代码,不像函数调用,须要等函数执行完成。主协程执行完毕,程序便退出,printHello 协程随即也退出,便不会有输出。.net
修改下代码:线程
func printHello() { fmt.Println("hello world goroutine") } func main() { go printHello() time.Sleep(1*time.Second) fmt.Println("main goroutine") } 复制代码
协程建立完成以后,main 协程先休眠 1s,预留给 printHello 协程执行的时间,因此此次输出:设计
hello world goroutine
main goroutine
复制代码
上一节就提到,能够建立多个协程,来看下例子:
func printNum() { for i := 1; i <= 5; i++ { time.Sleep(20 * time.Millisecond) fmt.Printf("%d ", i) } } func printChacter() { for i := 'a'; i <= 'e'; i++ { time.Sleep(40 * time.Millisecond) fmt.Printf("%c ", i) } } func main() { go printNum() go printChacter() time.Sleep(3*time.Second) fmt.Println("main terminated") } 复制代码
上面的代码,除主协程以外,新建立了两个协程:printNum 协程和 printChacter 协程。printNum 协程每隔 20 毫秒输出 5 个数,printChacter 协程每隔 40 毫秒输出字母。主协程建立完这两个协程以后休眠 1s,等待其余协程执行完成。 程序输出(你的输出可能跟个人不同):
1 a 2 3 b 4 5 c d e main terminated 复制代码
话说回来,经过加 time.Sleep() 函数等待协程执行完成是一种“黑科技”。在实际生产环境中,无论咱们是否知道其余协程执行完成须要多少时间,都不能在主协程中添加随机睡眠调用等待其余协程执行完成。那怎么办?Go 给咱们提供了信道,当协程执行完毕,可以通知到主协程,还可以实现协程间通讯。下节课咱们来讨论一下。
在函数那篇文章讲过,存在匿名函数,经过关键字 go 调用匿名函数就是匿名协程。咱们修改以前的例子:
func main() { go func() { fmt.Println("hello world goroutine") }() time.Sleep(1*time.Second) fmt.Println("main goroutine") } 复制代码
输出结果跟以前的同样。
但愿这篇文章给你带来收获,Good Day !
原创文章,若需转载请注明出处!
欢迎扫码关注公众号「Golang来啦」或者移步 seekload.net ,查看更多精彩文章。
给你准备了学习 Go 语言相关书籍,公号后台回复【电子书】领取!