协程
执行体是个抽象的概念,在操作系统层面有多个概念与之对应,比如操作系统自己掌管的
进程(process)、进程内的线程(thread)以及进程内的协程(coroutine,也叫轻量级线程)。与
传统的系统级线程和进程相比,协程的最大优势在于其“轻量级”,可以轻松创建上百万个而不
会导致系统资源衰竭,而线程和进程通常最多也不能超过1万个。这也是协程也叫轻量级线程的
原因。
多数语言在语法层面并不直接支持协程,而是通过库的方式支持,但用库的方式支持的功能
也并不完整,比如仅仅提供轻量级线程的创建、销毁与切换等能力。如果在这样的轻量级线程中
调用一个同步 IO 操作,比如网络通信、本地文件读写,都会阻塞其他的并发执行轻量级线程,
从而无法真正达到轻量级线程本身期望达到的目标。
Go 语言在语言级别支持轻量级线程,叫goroutine。Go 语言标准库提供的所有系统调用操作
(当然也包括所有同步 IO 操作),都会出让 CPU 给其他goroutine。这让事情变得非常简单,让轻
量级线程的切换管理不依赖于系统的线程和进程,也不依赖于CPU的核心数量。
goroutine是Go语言中的轻量级线程实现,由Go运行时(runtime)管理。你将会发现,它的
使用出人意料得简单。
假设我们需要实现一个函数Add(),它把两个参数相加,并将结果打印到屏幕上,具体代码
如下:
func Add(x, y int) {
z := x + y
fmt.Println(z)
}
那么,如何让这个函数并发执行呢?具体代码如下:
go Add(1, 1)
是不是很简单?
你应该已经猜到,“go”这个单词是关键。与普通的函数调用相比,这也是唯一的区别。的
确,go是Go语言中最重要的关键字,这一点从Go语言本身的命名即可看出。
在一个函数调用前加上go关键字,这次调用就会在一个新的goroutine中并发执行。当被调用
的函数返回时,这个goroutine也自动结束了。需要注意的是,如果这个函数有返回值,那么这个
返回值会被丢弃