Golang 并发性Goroutines
Go语言提供了一个特殊的功能,称为Goroutines。一个Goroutine是一个独立执行的函数或方法,它与程序中存在的任何其他Goroutine同时进行。换句话说,Go语言中每个同时执行的活动都被称为Goroutines。你可以把Goroutine看作是一个轻量级的线程。与线程相比,创建Goroutines的成本非常小。每个程序至少包含一个Goroutine,这个Goroutine被 称为主Goroutine。 所有的Goroutine都在主Goroutine下工作,如果主Goroutine终止了,那么程序中的所有Goroutine也就终止了。Goroutine总是在后台工作。
如何创建一个Goroutine
你可以通过使用go关键字作为函数或方法调用的前缀来创建你自己的Goroutine,如下面的语法所示。
语法
func name(){
// statements
}
// using go keyword as the
// prefix of your function call
go name()
例子
// Go program to illustrate
// the concept of Goroutine
package main
import "fmt"
func display(str string) {
for w := 0; w < 6; w++ {
fmt.Println(str)
}
}
func main() {
// Calling Goroutine
go display("Welcome")
// Calling normal function
display("GeeksforGeeks")
}
输出
GeeksforGeeks
GeeksforGeeks
GeeksforGeeks
GeeksforGeeks
GeeksforGeeks
GeeksforGeeks
在上面的例子中,我们简单地创建了一个display()函数,然后以两种不同的方式调用这个函数,第一种是Goroutine,即go display(“Welcome”),另一种是普通函数,即display(“GeeksforGeeks”) 。但是有一个问题,它只显示普通函数的结果,而不显示Goroutine的结果,因为当一个新的Goroutine执行时,Goroutine调用立即返回。控件不会像普通函数那样等待Goroutine完成其执行,它们总是在Goroutine调用后前进到下一行,并忽略Goroutine返回的值。因此,为了正确地执行Goroutine,我们在程序中做了一些修改,如下面的代码所示。
修改后的例子 。
// Go program to illustrate the concept of Goroutine
package main
import (
"fmt"
"time"
)
func display(str string) {
for w := 0; w < 6; w++ {
time.Sleep(1 * time.Second)
fmt.Println(str)
}
}
func main() {
// Calling Goroutine
go display("Welcome")
// Calling normal function
display("GeeksforGeeks")
}
输出
Welcome
GeeksforGeeks
GeeksforGeeks
Welcome
Welcome
GeeksforGeeks
GeeksforGeeks
Welcome
Welcome
GeeksforGeeks
GeeksforGeeks
我们在程序中添加了Sleep()方法,使主Goroutine休眠1秒,在1秒之间,新的Goroutine执行,在屏幕上显示 “欢迎”,然后在1秒后终止,主Goroutine重新计划并执行其操作。这个过程一直持续到z<6的值,然后主Goroutine就终止了。在这里,Goroutine和普通函数都是同时工作的。
Goroutine的优点
- Goroutine比线程更便宜。
- Goroutine存储在堆栈中,堆栈的大小可以根据程序的要求而增长和缩小。但在线程中,堆栈的大小是固定的。
- Goroutine可以使用通道进行通信,这些通道是专门为防止使用Goroutine访问共享内存时出现竞赛条件而设计的。
- 假设一个程序有一个线程,而这个线程有许多Goroutine与之相关。如果任何一个Goroutine由于资源需求而阻塞了线程,那么所有剩下的Goroutine将被分配给一个新创建的操作系统线程。所有这些细节都是对程序员隐藏的。
匿名Goroutine
在Go语言中,你也可以为一个匿名函数启动Goroutine,或者换句话说,你可以通过使用go关键字作为该函数的前缀来创建一个匿名Goroutine,如下图所示。
语法
// Anonymous function call
go func (parameter_list){
// statement
}(arguments)
例子
// Go program to illustrate how
// to create an anonymous Goroutine
package main
import (
"fmt"
"time"
)
// Main function
func main() {
fmt.Println("Welcome!! to Main function")
// Creating Anonymous Goroutine
go func() {
fmt.Println("Welcome!! to GeeksforGeeks")
}()
time.Sleep(1 * time.Second)
fmt.Println("GoodBye!! to Main function")
}
输出
Welcome!! to Main function
Welcome!! to GeeksforGeeks
GoodBye!! to Main function
极客教程