Go语言Goroutine

news2025/1/13 2:53:49

在本教程中,我们将讨论如何使用 Goroutines 在 Go 中实现并发。

什么是 Goroutine?

Goroutine 是与其他函数或方法同时运行的函数或方法。Goroutines 可以被认为是轻量级线程。与线程相比,创建 Goroutine 的成本很小。因此,Go 应用程序同时运行数千个 Goroutine 是很常见的。

Goroutines 相对于线程的优点

  • 与线程相比,Goroutines 非常便宜。它们的堆栈大小只有几 kb,并且堆栈可以根据应用程序的需要增长和缩小,而在线程的情况下,堆栈大小必须指定并且是固定的。
  • Goroutines 被复用到较少数量的操作系统线程。一个具有数千个 Goroutine 的程序中可能只有一个线程。如果该线程中的任何 Goroutine 阻塞等待用户输入,则会创建另一个操作系统线程,并将剩余的 Goroutine 移动到新的操作系统线程。所有这些都由运行时处理,我们作为程序员从这些复杂的细节中抽象出来,并获得一个干净的 API 来处理并发。
  • Goroutine 使用通道进行通信。通道的设计可防止使用 Goroutines 访问共享内存时发生竞争条件。通道可以被认为是 Goroutine 用来进行通信的管道。我们将在下一个教程中详细讨论通道。

如何启动 Goroutine?

在函数或方法调用前加上关键字前缀go,您将有一个新的 Goroutine 同时运行。

让我们创建一个 Goroutine

package main

import (  
    "fmt"
)

func hello() {  
    fmt.Println("Hello world goroutine")
}
func main() {  
    go hello()
    fmt.Println("main function")
}

Run program in playground

在11行号中。go hello()启动一个新的Goroutine。现在该hello()函数将与该main()函数同时运行。main 函数在自己的 Goroutine 中运行,称为main Goroutine

运行这个程序你会有惊喜!

该程序仅输出文本main function。我们启动的 Goroutine 发生了什么?我们需要了解 goroutine 的两个主要属性才能理解为什么会发生这种情况。

  • 当一个新的 Goroutine 启动时,goroutine 调用立即返回。与函数不同,控件不会等待 Goroutine 完成执行。Goroutine 调用后,控件立即返回到下一行代码,并且 Goroutine 的任何返回值都将被忽略。
  • 主 Goroutine 应运行,以便其他 Goroutine 运行。如果主 Goroutine 终止,则程序将终止,并且不会运行其他 Goroutine。

我想现在你应该能够理解为什么我们的 Goroutine 没有运行了。

现在让我们解决这个问题。

package main

import (  
    "fmt"
    "time"
)

func hello() {  
    fmt.Println("Hello world goroutine")
}
func main() {  
    go hello()
    time.Sleep(1 * time.Second)
    fmt.Println("main function")
}

Run program in playground

在上面程序的第 13 行中,我们调用了time包的Sleep方法,该方法使正在执行的 go 协程休眠。在这种情况下,主 goroutine 会休眠 1 秒。现在,在主 Goroutine 终止之前,对 go hello()的调用有足够的时间执行。该程序首先打印,``Hello world goroutine`

这种在主 Goroutine 中使用 sleep 来等待其他 Goroutine 完成执行的方式是我们用来理解 Goroutines 如何工作的一种 hack。Channels 可用于阻塞主 Goroutine,直到所有其他 Goroutine 完成执行。我们将在下一个教程中讨论通道。

启动多个 Goroutine

让我们再编写一个启动多个 Goroutine 的程序,以更好地理解 Goroutine。

package main

import (  
    "fmt"
    "time"
)

func numbers() {  
    for i := 1; i <= 5; i++ {
        time.Sleep(250 * time.Millisecond)
        fmt.Printf("%d ", i)
    }
}
func alphabets() {  
    for i := 'a'; i <= 'e'; i++ {
        time.Sleep(400 * time.Millisecond)
        fmt.Printf("%c ", i)
    }
}
func main() {  
    go numbers()
    go alphabets()
    time.Sleep(3000 * time.Millisecond)
    fmt.Println("main terminated")
}

Run program in playground

上面的程序启动了两个 Goroutine。这两个 Goroutine 现在同时运行。Goroutinenumbers最初休眠 250 毫秒,然后打印1,然后再次休眠并打印2,同样的循环发生,直到打印 5。类似地,alphabetsGoroutine 打印字母从ae并有 400 毫秒的休眠时间。主 Goroutine 启动numbersalphabetsGoroutines,休眠 3000 毫秒,然后终止。

该程序输出

1 a 2 3 b 4 c 5 d e main terminated  

下图描述了该程序的工作原理。请在新选项卡中打开图像以获得更好的可见性:)

img

蓝色图像的第一部分代表数字Goroutine,栗色第二部分代表字母 Goroutine,绿色第三部分代表主 Goroutine,最后黑色部分融合了上述三个部分,并向我们展示了如何程序有效。每个框顶部的0 ms、250 ms 等字符串表示以毫秒为单位的时间,输出在每个框的底部表示为1、2、3等。蓝色框告诉我们 是在 1打印之后 的250 ms,之后打印的2,依此类推。最后一个黑框的底部有值,1 a 2 3 b 4 c 5 d e main terminated这也是程序的输出。该图像是不言自明的,您将能够理解该程序是如何工作的。

Goroutines 就这样了。祝你有美好的一天。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1127807.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI基础软件:如何自主构建大+小模型?

导读&#xff1a;AI 基础软件作为大型 AI 模型的底座&#xff0c;承载着顶层大模型的建设&#xff0c;也是大模型应用落地的关键。为了更好地支持大模型的训练和演进&#xff0c;设计与开发基础软件便显得尤为重要。本文分享了九章云极DataCanvas如何自主构建大 小模型的经验与…

1024程序员节:理解编码背后的艺术

1024的含义 "1024"在中国互联网文化中有两个主要的含义&#xff1a; 1024是2的10次方&#xff0c;这在计算机科学中是一个重要的数字&#xff0c;因为计算机的基础是二进制。因此&#xff0c;程序员们常常把1024作为一个特殊的日子来庆祝&#xff0c;也就是10月24日…

如何把项目上传到Gitee(详细教程)

找到项目根目录右键打开Git Bash Here 输入命令&#xff1a;git init 回车 输入命令&#xff1a;git status 输入命令&#xff1a;git add . 输入命令&#xff1a;git status git commit -m 项目描述 在Gitee官网注册好账号后&#xff0c;git 新建项目 填写补充git项目信息及…

SAP采购发票差异处理

&#xff08;一&#xff09; 税金差异 一般情况下&#xff0c;供应商的开票金额与我们的入库金额一致&#xff0c;不过有时也会出现不一致的情况&#xff0c;如通过金税系统开票出现尾差&#xff0c;或是开票价格大于订单价格。本文介绍如何处理采购发票中的税金差异。 采购订…

【单调栈】84. 柱状图中最大的矩形、60天刷题总结

提示&#xff1a;努力生活&#xff0c;开心、快乐的一天 文章目录 84. 柱状图中最大的矩形&#x1f4a1;解题思路&#x1f914;遇到的问题&#x1f4bb;代码实现&#x1f3af;题目总结 总结数组链表哈希表数组作为哈希表set作为哈希表map作为哈希表 字符串要不要使用库函数双指…

Jmeter接口测试(十一):BeanShell脚本详解

BeanShell简介 BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些 语法和方法&#xff1b; BeanShell是一种松散类型的脚本语言&#xff1b; BeanShell是用Java写成的&#xff0c;一个小型的、免费的、可以下载、嵌入式的 Java源代码解释器&#xff0c;具…

Vue脚手架的安装和分析

一、Vue脚手架的安装步骤 &#xff08;一&#xff09;全局安装Vue脚手架 Window R&#xff0c;输入cmd进入电脑终端。 在终端中输入如下命令全局安装Vue脚手架&#xff1a; npm install -g vue/cli 下载过程中会警告&#xff0c;但不用关心这个。 &#xff08;二&#xff…

经管博士科研基础【26】海塞矩阵

1. 海塞矩阵 海塞矩阵是一个由多变量实值函数的所有二阶偏导数组成的方块矩阵。 一元函数就是二阶导,多元函数就是二阶偏导组成的矩阵。求向量函数最小值时可以使用,矩阵正定是最小值存在的充分条件。经济学中常常遇到求最优的问题,目标函数是多元非线性函数的极值问题,尚…

许战海方法论日文版正式发布,多家日媒转发

10月18日&#xff0c;日本财经媒体掀起了一场轻微的风潮&#xff0c;近40家权威媒体纷纷转发了一条引人注目的新闻:帆をあげて、海へ」、許戦海方法論の日本語版が正式に発表(扬帆起航&#xff1a;许战海方法论日文版正式发布)。 日本焦点新闻、阿波罗新闻、乐天新闻等权威媒体…

vue3 源码解析(1)— reactive 响应式实现

前言 本文是 vue3 源码解析系列的第一篇文章&#xff0c;项目代码的整体实现是参考了 v3.2.10 版本&#xff0c;项目整体架构可以参考之前我写过的文章 rollup 实现多模块打包。话不多说&#xff0c;让我们通过一个简单例子开始这个系列的文章。 举个例子 <!DOCTYPE html…

安科瑞带防逆流功能的数据通讯网关-安科瑞黄安南

AWT200 数据通讯网关应用于各种终端设备的数据采集与数据分析。用于实现设备的监测、控制、计算&#xff0c;为系统与设备之间建立通讯纽带&#xff0c;实现双向的数据通讯。实时监测并及时发现异常&#xff0c;同时自身根据用户规则进行逻辑判断&#xff0c;可以节省人力和通讯…

2023年面试测试工程师一般问什么问题?

面试和项目一起&#xff0c;是自学路上的两大拦路虎。面试测试工程师一般会被问什么问题&#xff0c;总结下来一般是下面这4类&#xff1a; 1.做好自我介绍 2.项目相关问题 3.技术相关问题 4.人事相关问题 接下来&#xff0c;主要从以上四个方向分别展开介绍。为了让大家更有获…

[ThinkPHP]The namespace “work“ is ambiguous (worker, workflow)

问题截图&#xff1a; 解决办法&#xff1a; console.php增加相关配置

PAM从入门到精通(二十三)

接前一篇文章&#xff1a;PAM从入门到精通&#xff08;二十二&#xff09; 本文参考&#xff1a; 《The Linux-PAM Application Developers Guide》 先再来重温一下PAM系统架构&#xff1a; 更加形象的形式&#xff1a; 七、PAM-API各函数源码详解 前边的文章讲解了各PAM-API…

方案聚焦:高可用的F5分布式云DNS负载均衡

DNS是实现互联网的主要技术之一。它也是网络基础设施的重要组成部分&#xff0c;DNS管理一个分布式和冗余的架构&#xff0c;确保高可用性和高质量的用户响应时间&#xff0c;因此拥有一个可用的、智能的、安全和可扩展的DNS基础设施是至关重要的。然而DNS没有真正的能力来分配…

如何有效取代FTP来帮助企业快速传输大文件

在互联网的发展历史上&#xff0c;FTP是一种具有里程碑意义的协议&#xff0c;它最早出现在1971年&#xff0c;是实现网络上文件传输的基础。FTP的优点是简单、稳定、兼容性强&#xff0c;可以在不同的操作系统和平台之间进行文件交换。然而&#xff0c;时代在进步&#xff0c;…

系统升级数量超微软预期,Win10/11盗版激活被封杀

声明&#xff1a;本文提供的命令、工具来自第三方网站&#xff0c;仅供学习交流使用&#xff0c;下载后24小时内删除&#xff0c;一切非法使用责任由使用者自行承担。 上月底 Win11 迎来了 Moment 4 功能更新&#xff0c;任务栏取消合并居然真的回归了。 巨硬终于妥协&#x…

软件开发行业的乱象——低价引流中途收费?299?399?

在当今的软件开发行业&#xff0c;存在着许多乱象。这些乱象不仅影响了软件开发的效率和效果&#xff0c;也给整个行业带来了许多负面影响。其中&#xff0c;价格方面是软件开发行业乱象的一个重要方面。 首先&#xff0c;从价格方面来看&#xff0c;软件开发行业的价格标准非常…

【均值漂移】mean-shift算法详解

Mean-shift算法是一种非参数密度估计算法&#xff0c;主要用于图像分割、目标跟踪和聚类等领域。其基本原理是以某个点为中心&#xff0c;计算该点周围所有点的密度&#xff0c;并将中心点移动到密度最大的位置&#xff0c;不断迭代&#xff0c;直到中心点不再移动或满足停止条…

常用智能优化算法改进策略---飞行游走篇(五种策略)可用于改进所有智能算法,让小白也会改进智能算法。...

本期文章将讲述常用智能优化算法改进策略---飞行游走篇&#xff0c;一共包含五种常见的改进策略&#xff1a; ①莱维飞行&#xff0c;②随机游走&#xff0c;③螺旋飞行&#xff0c;④高斯随机游走&#xff0c;⑤三角形游走 五种策略可以方便移植到其他任何智能算法的改进中&am…