那么,goroutines是什么呢?

那么,goroutines是什么呢?_第1张图片
图像没有过分夸张

到目前为止,对并发的本机支持是Go最受欢迎的功能之一,它使开发人员可以轻松地创建并发应用程序。 为了利用本机并发,需要使用goroutines。

Goroutines可被视为Go的主干,并且在设计固有的并发应用程序中很重要。

因此,让我们了解什么是goroutines。

什么是Goroutines

可以将Goroutine与轻量级线程进行比较。 它们只是与其他功能或方法同时运行的功能或方法。

它们使我们能够在同一地址空间中同时创建和运行多个功能,并且安装成本不高。

Goroutines与线程

Go使用goroutine,而其他语言(例如Java)则使用线程。 Goroutine很便宜(大约2 Kb),因为线程需要更多的堆栈空间,因此它们通常占用大量内存(从1 Mb开始)。 这使开发人员可以创建线程无法实现的大量goroutine。

所以您可能会问,为什么goroutines如此轻巧?

好吧,goroutines如此轻便的原因是因为Go不使用传统的本机线程,而是使用了绿色线程。 本机线程或OS线程具有单独的函数调用堆栈,因此它们的设置和拆卸成本非常可观。

让我们看看Go是如何做到的。

因此,在运行时,调度程序将goroutine映射到线程上,但是与Java线程中的1:1映射不同,一堆goroutine被映射到单个或一组线程上。 此外,goroutine具有灵活的堆栈大小,可根据需要扩展和缩小。 这显着减少了内存占用,并改善了goroutine的内存重新分配时间。

但是您完全不必担心所有这些漂亮的细节。

Go在运行时会处理所有这些任务,并从用户中抽象出来。

因此,用户可以做自己最擅长的事情,编写简洁高效的代码,而不必担心堆栈分段和内存重新分配。

那么,goroutines是什么呢?_第2张图片
地鼠书类似罗伯·派克(Rob Pike)的演讲

如何启动Goroutine

goroutine的启动非常简单,只需使用关键字go即可完成 在函数或方法的前面,您就可以准备同时运行goroutine了。

package main

import (
"fmt"
)

func hello() {
fmt.Println("Hi, I'm a goroutine!")
}
func main() {
go hello()
fmt.Println("Inside main function")
}

上面的代码将创建一个goroutine与func main()并发运行, func main()执行它自己的goroutine,称为main goroutine。

goroutine的创建非常简单,您不必担心后台的细节,因为它们都是在Go运行时处理的。

可是等等..

执行代码后,您会收到一些惊喜!

Inside main function

该代码仅打印来自func main()的消息,而不打印来自func hello()的消息。 可以解释如下:

  1. 启动goroutine时,goroutine调用会立即返回。 这意味着控件不会等待goroutine完成执行才能继续执行下一个功能或goroutine。
  2. 同样,主goroutine应该正在运行,以便其他任何goroutine能够运行。 它的终止将导致其他所有goroutine的终止,并且该程序将终止。

这就是上面我们的代码所发生的。 在呼叫go hello ,控件将消息打印在主函数中,然后程序终止。 func hello()没有机会执行,因为主goroutine已终止并且程序结束了。

解决问题的方法

确切地说,这更多的是破解而不是修复,因为我们将程序的执行限制在现实世界的时间范围内,但这对于本示例来说就足够了。 请注意,这是一种不好的做法,应避免使用,因为实际上我们总是将通道用于任何此类同步。

package main

import (
"fmt"
"time"
)

func hello() {
fmt.Println("Hi, I'm a goroutine!")
}
func main() {
go hello()
time.Sleep(1 * time.Second)
fmt.Println("Inside main function")
}

time.sleep(1 * time.Second)当前goroutine进入睡眠状态,并为hello goroutine提供足够的时间来完成操作。

现在,当我们运行程序时,我们得到的两条消息的间隔均为1秒。

Hi, I'm a goroutine! 
Inside main function

总结思想

默认情况下,Go使用的CPU线程数等于存在的CPU内核数。 您可以通过以下语句runtime.GOMAXPROCS(-1)获得线程数runtime.GOMAXPROCS(-1)

可以通过将值从1更改为任意数字来更改线程数,但是在选择它们时必须小心。 尽管更多的线程可以提高性能,但是太多的线程可以降低进程速度,因此,理想的数量只能在运行性能扫描后确定。

Go的本机并发模型使它在创建真正的并发系统方面越来越受欢迎,而goroutines是其功能的重要组成部分。 它们可以被视为语言的心脏和灵魂,如果使用得当,它们可以大大提高性能。

并发不是并行

我在帖子中已经多次使用并发性,但是如果您仍然想将“并发性”和“并行性”一词互换使用,那么您应该看一下Rob Pike对该主题的看法了 。

From: https://hackernoon.com/goroutines-a-general-introduction-49bed9812c94

你可能感兴趣的:(那么,goroutines是什么呢?)