Go轻量级线程Goroutine

news2024/10/6 6:01:27

文章目录

    • Goroutine
        • goroutine的创建
        • GPM介绍
        • goroutine调度

道阻且长,行则将至,行而不辍,未来可期🌟。人生是一条且漫长且充满荆棘的道路,一路上充斥着各种欲望与诱惑,不断学习,不断修炼,不悔昨日,不畏将来!
希望这篇能够带给你们或多或少的帮助,诸位!顶峰见 🚀

Goroutine

  • Golang中最迷人的一个优点就是从语言层面就支持并发
  • 在Golang中的goroutine(协程)类似于其他语言的线程

我们可以理解goroutine是一个轻量级线程,所占用的栈空间很小(一般为2KB)且可以扩容与减小

goroutine的创建

在Go语言内可以通过go func来创建一个goroutine

package main

func hello()  {
	fmt.Println("Hello")
}

func main() {
	go hello()

	fmt.Println("Main")
}

Go程序开始时会创建一个 main goroutine。我们通过go关键字也会创建一个goroutine去执行hello程序,而此时main goroutine会继续执行。
此时程序里面会有两个goroutine并发执行,当main函数结束后 main goroutine会结束,由main goroutine创建的其它goroutine也会立即结束
所以这里hello是有可能打印不出来的

执行结果:

Main

所以为了避免main函数代码运行结束,而其它goroutine仍在运行中,所以我们需要main函数阻塞等待其它goroutine执行结束

暴力等待可通过time.Sleep 。这里使用sync模块,利用计数等待实现

package main

import (
	"fmt"
	"sync"
)

var ws sync.WaitGroup

func hello() {
	// goroutine函数结束后,Done表示计数减1
	defer ws.Done()

	fmt.Println("Hello")
}

func main() {
	// 开启一个goroutine之前进行计数
	ws.Add(1)

	go hello()

	fmt.Println("Main")

	// 当计数为0的时候才结束,否则阻塞等待
	ws.Wait()
}

执行结果:

Main
Hello

GPM介绍

在这里插入图片描述

操作系统的线程一般都有固定的栈(通常为2MB),而Go语言中的goroutine非常轻量级,一个goroutine的初始栈空间很小(一般为2KB),并且goroutine的栈空间大小不是固定的,通常可以根据内容进行扩容增大或减小,Go的runtime会自动分配合适的goroutine的栈空间。

由于线程间切换需要进行一个完整的上下文切换过程开销较大,Go语言本身具有一套调度goroutine的系统。它将按照一定规则将goroutine调度到操作系统线程上执行,经过数个版本的迭代,Go语言调度器目前按照GPM模型

  • G:表示goroutine,通过go func关键字创建,包含执行的函数和上下文信息

    全局队列:存放等待运行的G

  • P:表示goroutine执行所需要的资源,最多有GOMAXPROCS个(CPU的核心)

    P本地队列:也是存放等待运行G的地方,创建G之后会优先放到P的队列,不过P队列存放的G数量有限,不超过256。如果P本地队列满了则会批量移动部分G到全局队列

  • M:线程想运行任务就得获取P。从P本地队列获取G,如果P队列为空,则尝试从其它的P队列获取都没有的话则尝试从全局队列获取。M运行G,G执行之后,M又会继续获取G,不断重复

goroutine调度器和操作调度器是通过M结合的,每个M代表1个内核线程,操作系统调度器负责把内核线程分配到CPU核上运行

从线程来讲:Go语言的goroutine相较于其它语言开启线程的优势在于,其它线程的线程是由内核来调度的,goroutine则是Go语言运行时自己调度的,完全是在用户态下面完成的,不涉及内核与用户态之间频繁切换

goroutine调度

goroutine的执行顺序并不是按照创建时间来的,而是取决于哪个G优先被M执行


猜测该函数执行后的打印结果:

func f() {
	ws.Add(5)
	for i := 0; i < 5; i++ {
		go func() {
			fmt.Println(i)
			ws.Done()
		}()
	}
}

执行结果:

5
5
5
5
5

程序解析:

go关键字会创建goroutine去执行里面的匿名函数,而从创建->执行中间需要一定的时间,而for循环却在继续,匿名函数里面访问的是外部变量i,所以在实际执行到这个goroutine的时候,循环可能已经结束了,而i的值最终会变成5。所以大部分情况会打印5 5 5 5 5。也可能存在goroutine执行较快的情况,某个goroutine在循环未结束之前就执行了,可能会打印出其它数字。

猜测该函数执行后的打印结果:

func f2() {
	ws.Add(5)
	for i := 0; i < 5; i++ {
		go func(j int) {
			fmt.Println(j)
			ws.Done()
		}(i)
}

程序解析:

该函数与f不同的是,i由于传递到了匿名函数里面,那么打印的值是确认的,而由于goroutine并不是按顺序执行的,所以最终打印的结果就是:所有数字都会打印出来,只是顺序不同

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

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

相关文章

第二十一章:用户与权限管理

第二十一章&#xff1a;用户与权限管理 21.1&#xff1a;用户管理 登录MySQL服务器 # 语法 mysql -h hostname|hostIP -P port -u username -p DatabaseName -e "SQL语句"; # -h参数 后面接主机名或者主机IP&#xff0c;hostname为主机&#xff0c;hostIP为主机IP。…

请求响应-简单参数的接受

请求响应 请求&#xff08;HttpServletRequest&#xff09;&#xff1a;获取请求数据响应&#xff08;HttpServletResponse&#xff09;&#xff1a;设置响应数据BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构。客户端只需要浏览器&#xff0c;应用程序的逻…

BCD码与二进制码的区别与联系

二进制数是整串二进制编码表示一个整数&#xff0c;BCD码是用二进制码逐一表示0&#xff5e;9的整数。 (本笔记适合对整数进制编码有一定了解&#xff0c;熟悉二进制数编码的编程爱好的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org…

【python】制作一个串口工具(下)!

上一章节我们说了UI界面的设计&#xff0c;这一节来说下怎样实现其功能。 一.实例演示 1.创建一个.py文件&#xff0c;以下代码用来实现获取所有的串口信息&#xff1a; import serial import serial.tools.list_portsfrom PyQt5.QtWidgets import QComboBoxclass My_ComBoBo…

使用Feign进行微服务之间的接口调用:Spring Cloud Alibaba中的声明式服务调用

一、Feign介绍 Feign是一个声明式的HTTP客户端框架&#xff0c;用于简化微服务架构中服务之间的通信。它是Spring Cloud框架的一部分&#xff0c;旨在提供一种优雅且易于使用的方式来定义和调用HTTP请求。 Feign的设计目标是让服务之间的通信变得更加简单和直观。通常情况下&am…

EmEditor自定义快捷键之下一个标签页上一个标签页

EmEditor自定义快捷键 有好几种叫法 下一个标签页上一个标签页 下一个选项卡上一个选项卡 在这里个软件它叫’右侧文档’ ‘左侧文档’ 工具 - 所有配置的属性 - 键盘 - 窗口 - 类别: 选’窗口’ - 依次选 ‘右边的文档’ ‘左边的文档’ 按下新的快捷键 - 是每次只按一个键(不…

简单的复习下与 CSS Flex 布局相关的几个关键属性

揭开align-content、justify-content、align-items和justify-items的神秘面纱&#xff0c;解释它们各自的功能以及在不同的情境下如何使用。 在过去几年中&#xff0c;由于弹性盒子和网格布局的演变&#xff0c;CSS布局设计的艺术发生了重大变化。而这一变革的核心&#xff0c;…

CS231N assignment3 RNN

对作业进行一些形象的解释 首先是def rnn_step_forward&#xff1a; 这里的t时刻其实就是一个句子里面的单词数&#xff0c;为了方便会统一到一个最长长度&#xff0c;对于比这个长度短的部分用null进行填充&#xff0c;并且在方法内部会让Null不进行传播和梯度计算。 我们最…

AIGC的发展史:从模仿到创造,AI的创造性探索

在 AI时代&#xff0c;人工智能不再是简单的机器&#xff0c;而是一个具有无限创造力的创造者。AIGC的诞生是人工智能从模仿到创造的一种进步&#xff0c;也是对人类创造力的一种新探索。 而这种由AI生成的内容究竟是如何发展而来的呢&#xff1f;在本文中&#xff0c;我们将探…

QT检测USB HID设备的拔插

网上的参考代码很多&#xff0c;比如下面这个&#xff1a; QT 检测hid设备拔插打印设备信息_qt hid打印机_研知电子的博客-CSDN博客 但是&#xff0c;参考了很多人的代码&#xff0c;写出来的发现检测不到USB HID设备的拔插。 明明其他人都可以正常使用&#xff0c;那问题应…

java内存区 || 并发

目录 什么是线程&#xff1f; 线程的创建和上下文切换&#xff1a; 线程的入栈和出栈&#xff1a; 堆栈的作用&#xff1a; CPU核心数概念 线程的start状态 就绪队列 操作系统的时间片 线程中代码执行顺序 实际中内存图 什么是线程&#xff1f; 线程的创建和上下文切换…

【android12】给第三方应用APK添加系统签名

一、背景 自己或者客户的第三方apk需要用到很多系统权限&#xff0c;所以要内置到系统目录下&#xff0c;变成系统自带的APP&#xff0c;如果不用系统文件生成的签名安装&#xff0c;会导致APP远程更新失败提示签名错误。 二、环境准备 1.Ubuntu系统&#xff08;推荐1804版本及…

Invalid name=“org.apache.dubbo.config.ApplicationConfig#0“

上一篇文章是springboot 集成 dubbo&#xff1a; spring boot 集成dubbo_Demonor_的博客-CSDN博客 在集成的时候出现了一些异常&#xff0c;在这里记录一下&#xff0c;并排查出原因 异常信息1&#xff1a; [2m2023-07-11 20:38:39.387[0;39m [32m INFO[0;39m [35m21492[0;…

92.qt qml-日期/日期时间/时间选择器(日历选择器)

截图如下所示: 效果图如下所示: 1.前言 QML日历组件我们之前移植过: 67.qt quick-qml自定义日历组件(支持竖屏和横屏)_qml日历_诺谦的博客-CSDN博客 但是该组件内部代码比较坑的就是全部使用自定义对象,导致性能不行,动画卡顿,并且不好加时间选择,所以本章我们重新学…

Mysql 实现批量插入对已存在数据忽略或更新

Mysql 实现批量插入对已存在数据忽略/更新 文章目录 Mysql 实现批量插入对已存在数据忽略/更新一. 表的准备二. 实现2.1 实现原理2.2 批量插入对已存在数据忽略 一. 表的准备 CREATE TABLE demo (id int NOT NULL AUTO_INCREMENT COMMENT 主键id,name varchar(10) DEFAULT NUL…

重磅IntelliJ IDEA 2023.2 新版本即将发布,拥抱 AI

IntelliJ IDEA 近期连续发布多个EAP版本&#xff0c;官方在对用户体验不断优化的同时&#xff0c;也新增了一些不错的功能&#xff0c;尤其是人工智能助手补充&#xff0c;AI Assistant&#xff0c;相信在后续IDEA使用中&#xff0c;会对开发者工作效率带来不错的提升。 以下是…

基于A*的二维多无人机航线规划

Matlab航迹规划仿真——A*算法_航迹起始算法 matlab_致守的博客-CSDN博客 matlab2016及以上可以运行 astar.m function [] astar(Spoint,Epoint,Matrix,m,n,h1,h2) %%寻路 Matrix(Spoint(1),Spoint(2))0; Matrix(Epoint(1),Epoint(2))inf; GMatrix; FMatrix; openlistMatri…

安全防御 --- DDOS攻击(01)

DOS攻击&#xff08;deny of service&#xff09;--- 拒绝式服务攻击 例&#xff1a;2016年10月21日&#xff0c;美国提供动态DNS服务的DynDNS遭到DDOS攻击&#xff0c;攻击导致许多使用DynDNS服务的网站遭遇访问问题&#xff0c;此事件中&#xff0c;黑客人就是运用了DNS洪水…

ceph--RBD的使用

Ceph-RDB 1、RBD架构图 Ceph 可以同时提供对象存储 RADOSGW、块存储 RBD、文件系统存储 Ceph FS,RBD 即 RADOS Block Device 的简称&#xff0c;RBD 块存储是常用的存储类型之一&#xff0c;RBD 块设备类似磁盘 可以被挂载&#xff0c;RBD 块设备具有快照、多副本、克隆和一致…

今天实习第一天,用git

老板问了我是否用过gitee&#xff0c;并且是否用过git&#xff0c;在集成工具中&#xff0c;会git来提交代码。我说没有。 所以&#xff0c;先使用gitee。 01.登录gitee的官网&#xff0c;在此处登录。 02.绑定邮箱&#xff0c;我用的是QQ邮箱。