📜  Goroutines – Golang 中的并发

📅  最后修改于: 2021-10-25 03:03:43             🧑  作者: Mango

Go 语言提供了一个称为 Goroutines 的特殊功能。 Goroutine 是一个函数或方法,它与程序中存在的任何其他 Goroutines 相关联地独立并同时执行。或者换句话说,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 在新 Goroutine 执行的 1 秒之间休眠 1 秒,在屏幕上显示“欢迎”,然后在 1 秒主 Goroutine 重新调度和执行其操作。这个过程一直持续到z<6的值,然后主 Goroutine 终止。在这里,Goroutine 和普通函数同时工作。

Goroutine 的优点

  • Goroutines 比线程便宜。
  • Goroutine 存储在堆栈中,堆栈的大小可以根据程序的要求进行增减。但是在线程中,堆栈的大小是固定的。
  • Goroutines 可以使用通道进行通信,这些通道专门设计用于在使用 Goroutines 访问共享内存时防止竞争条件。
  • 假设一个程序有一个线程,并且该线程有许多与之关联的 Goroutine。如果任何 Goroutine 因资源需求而阻塞线程,则所有剩余的 Goroutine 将分配给新创建的 OS 线程。所有这些细节对程序员都是隐藏的。

匿名协程

在 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