当前位置: 首页 > news >正文

[Golang] goroutine

[Golang] goroutine

文章目录

  • [Golang] goroutine
    • 并发
      • 进程和线程
      • 协程
    • goroutine
      • 概述
      • 如何使用goroutine

并发

进程和线程

谈到并发,大多都离不开进程和线程,什么是进程、什么是线程?

  • 进程可以这样理解:进程就是运行着的程序,它是程序在操作系统的一次执行过程,是一个程序的动态概念,进程是操作系统分配资源的基本单位

  • 线程可以这样理解:线程是一个进程的执行实体,它是比进程粒度更小的执行单元,也是真正运行在cpu上的执行单元,线程是CPU调度资源的1基本单位

进程可以包含多个进程,需要记住的是进程和线程,一个是操作系统分配资源的基本单位,一个是操作系统调度的基本单位。

协程

协程可以理解为用户态线程,是更轻量级的线程。区别于线程,协程的调度在用户态进行,不需要切换到内核态,所以不由操作系统参与,由用户自己控制。在一些支持协程的高级语言中,大多都实现了自己的协程调度器,比如golang就有GMP模型、python就有asyncio等等。

  • 协程有独立的栈空间,但是共享堆空间
  • 一个进程可以跑多个线程,一个线程可以跑多个协程

goroutine

概述

goroutine就是golang对协程的支持,可以把它理解为golang的协程。

golang的并发只会用到goroutine,所以我们并不用去考虑使用进程、线程。一般线程栈本身大小大约是2MB,而且线程在切换上下文时是消耗资源的,会带来性能消耗,所以我们往往在使用多线程技术时,会通过池化技术,即创建线程池来管理一定数量的线程。

但是在golang中,一个goroutine栈在一开始占用的空间很小,一般只有2KB,并且它的栈大小可以按需求变大或者变小,最大时可以达到1GB(但是一般不用这么大)。所以在golang中一次创建成千上万个或10万个协程理论上也是有可能的。

在golang中,我们使用goroutine完成并发,在某个任务需要并发执行时,只需要把这个任务包装成一个函数,去开启一个goroutine去执行这个函数即可。我们不用维护一个线程池类似的东西,也不需要去关心协程是怎么切换和调度的,因为golang已经内置了调度器帮我们做了,并且效率非常高。

如何使用goroutine

func()
go func()//并发执行

和其他语言相同,golang程序的入口就是main函数。在程序开始执行时,Go程序会为main函数创建一个默认的goroutine,我们称为主协程,我们后来人为的创建的一些goroutine,都是在这个主协程上执行的。

比如:

package mainimport "fmt"func myGoroutine() {fmt.Println("son")
}func main() {go myGoroutine()fmt.Println("father")
}

运行结果:

image-20240912204217798

但是为什么只有主协程在打印,我们创建的协程没有进行打印呢?

这是因为,当main()函数返回时这个goroutine也就是结束了,主协程结束,其他协程不管是不是运行完,都会跟着结束。所以,当主协程打印完“father”返回后,myGoroutine协程还没来的及运行到打印也就是跟着返回了。

所以,我们想看到都打印,只需要让主协程等待几秒就可以了。

package mainimport ("fmt""time"
)func myGoroutine() {fmt.Println("son")
}func main() {go myGoroutine()fmt.Println("father")time.Sleep(2 * time.Second)
}

运行结果:

image-20240912204705774

后面还有更好的方法,不用再让主协程睡眠了。

比如:

package mainimport ("fmt""sync""time"
)func myGoroutine(name string, wg *sync.WaitGroup) {defer wg.Done()for i := 0; i < 2; i++ {fmt.Printf("myGoroutine %s\n", name)time.Sleep(1 * time.Second)}
}func main() {var wg sync.WaitGroupwg.Add(2)go myGoroutine("张三", &wg)go myGoroutine("李四", &wg)time.Sleep(2 * time.Second)wg.Wait()
}

运行结果:

image-20240912205414100

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 2023年06月中国电子学会青少年软件编程(Python)等级考试试卷(二级)答案 + 解析
  • 【sgCreateCallAPIFunction】自定义小工具:敏捷开发→调用接口方法代码生成工具
  • 通过防火墙分段增强网络安全
  • Java | Leetcode Java题解之第409题最长回文串
  • 【MySQL】表的操作【有关表结构的操作】【创建、查看、删除、修改表结构】
  • 人工智能与机器学习原理精解【21】
  • SRE实例的一些结构图
  • javascript-装饰器
  • Invoke-Maldaptive:一款针对LDAP SearchFilter的安全分析工具
  • Java stream().anyMatch
  • 无线安全(WiFi)
  • vulnhub(8):pWnOS(还没信息收集就已经成功打点)
  • 最佳实践 · MySQL 分区表实战指南
  • Java 实现桌面烟花秀
  • 树——数据结构
  • Google 是如何开发 Web 框架的
  • Invalidate和postInvalidate的区别
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • Linux下的乱码问题
  • Netty源码解析1-Buffer
  • React-redux的原理以及使用
  • SAP云平台里Global Account和Sub Account的关系
  • Vue2 SSR 的优化之旅
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 构造函数(constructor)与原型链(prototype)关系
  • 基于游标的分页接口实现
  • 记录一下第一次使用npm
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 模型微调
  • 如何进阶一名有竞争力的程序员?
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • ​14:00面试,14:06就出来了,问的问题有点变态。。。
  • ​埃文科技受邀出席2024 “数据要素×”生态大会​
  • ###C语言程序设计-----C语言学习(6)#
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (12)Hive调优——count distinct去重优化
  • (function(){})()的分步解析
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (待修改)PyG安装步骤
  • (二)十分简易快速 自己训练样本 opencv级联lbp分类器 车牌识别
  • (分布式缓存)Redis持久化
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (函数)颠倒字符串顺序(C语言)
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (强烈推荐)移动端音视频从零到上手(下)
  • (四)Controller接口控制器详解(三)
  • (图文详解)小程序AppID申请以及在Hbuilderx中运行
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (转)ORM
  • (转)Sublime Text3配置Lua运行环境
  • (转)创业家杂志:UCWEB天使第一步