草庐IT

Go语言入门12(协程 goroutine)

te9uila 2023-12-29 原文

协程

进程和线程

进程

​ 当运行一个应用程序的时候,操作系统会为这个应用程序启动一个进程。可以将这个进程看作一个包含了应用程序在运行中需要用到和维护的各种资源的容器。这些资源包括但不限于内存地址空间、文件和设备的句柄以及线程

线程

​ 一个线程是一个执行空间,这个空间会被操作系统调度来运行函数中所写的代码。每个进程至少包含一个线程,每个进程的初始线程被称作主线程。因为执行这个线程的空间是应用程序的本身的空间,所以当主线程终止时,应用程序也会终止。操作系统将线程调度到某个处理器上运行,这个处理器并不一定是进程所在的处理器

并发和并行

并发

​ 并发是指在一个逻辑处理器同时管理很多事情,这些事情可能只做了一半就被暂停去做别的事情了,golang的并发通过切换多个线程打到减少物理处理器空闲等待的目的

并行

​ 并行是让不同的代码片段同时在不同的物理处理器上执行,大多数情况下,并发的效果比并行好,因为操作系统的硬件的总资源一般很少,但能支持系统同时做很多事情

goroutine协程

在一个协程中运行函数

​ 在一个协程中运行一个函数其实很简单,只要在函数调用前加上go即可

// 随便写一个demo函数
func Demo01(num int, contain string) {
	for i := 0; i < num; i++ {
		fmt.Println("这是一个goroutine", contain)
	}
}
// 在协程中运行此函数
func main() {
    go Demo01(10,"调用Demo函数")
	fmt.Println("over!")
}
//输出:
//   over!

​ 上述代码由于demo调用在协程中进行,所以并不影响主函数的运行,当主函数运行结束之后,代码运行直接停止,所以协程并没有输出任何内容,因此我们可以使用sleep方法让主函数进入等待状态

// 随便写一个demo函数
func Demo01(num int, contain string) {
	for i := 0; i < num; i++ {
		fmt.Println("这是一个goroutine", contain)
	}
}
// 在协程中运行此函数
func main() {
    go Demo01(10,"调用Demo函数")
    time.Sleep(1000000000)
	fmt.Println("over!")
}
//输出:
//   这是一个goroutine demo调用
//   这是一个goroutine demo调用
//   这是一个goroutine demo调用
//   这是一个goroutine demo调用
//   这是一个goroutine demo调用
//   over!

​ 但是这样子让主函数等待协程运行,听起来是个蛮蠢的想法,我们可以使用一个另一种方式解决问题,Waitgroup方法

waitgroup方法

​ 我们可以在使用waitgroup方法先实例化一个计数器,wg,在协程中使用wg.done进行操作计数器,从而达到主函数等待协程运行的一个目的

// demo方法
// 同时因为我们要对wg进行操作,因此要把wg的指针传递给函数
func Demo01(num int, contain string, wg *sync.WaitGroup) {
    // 因为wg,done一般来说都在函数最后使用,因此我们把他放在defer延迟处理函数里面
	defer wg.Done()
	for i := 0; i < num; i++ {
		fmt.Println("这是一个goroutine", contain)
		time.Sleep(1000000000)
	}
}

// main方法
func main() {
    // 实例化计数器wg
	var wg sync.WaitGroup
    // 要运行两个goroutine函数
	wg.Add(2)
	go functions.Demo01(2, "the first goroutine!", &wg)
	go functions.Demo01(3, "the second goroutine!", &wg)
    // 等待两个goroutine运行完毕
	wg.Wait()
    // 执行完毕后再输出over!
	fmt.Println("over!")
}
// 输出:
// 这是一个goroutine the second goroutine!
// 这是一个goroutine the first goroutine!
// 这是一个goroutine the first goroutine!
// 这是一个goroutine the second goroutine!
// 这是一个goroutine the second goroutine!
// over!

并发执行

​ 前文说过,并发执行就是让协程运行在同一个逻辑处理器上,我们可以在主方法中使用runtime.GOMAXPROCS(1)强制控制在一个逻辑处理器中

// main方法
func main() {
    routine.GOMAXPROCS(1)
    // 实例化计数器wg
	var wg sync.WaitGroup
    // 要运行两个goroutine函数
	wg.Add(2)
	go functions.Demo01(2, "the first goroutine!", &wg)
	go functions.Demo01(3, "the second goroutine!", &wg)
    // 等待两个goroutine运行完毕
	wg.Wait()
    // 执行完毕后再输出over!
	fmt.Println("over!")
}

​ 这样子会让处理器在两个工作中不断的切换,而并不是真正的同时进行,而真正的同进行,需要并行执行

并行执行

​ 并行执行就是让各个goroutine都在单独的逻辑处理器中运行,这时runtime.GOMAXPROCS(tmp)中的tmp参数就应给等于你的goroutine个数,同时我们可以使用runtime.NumCPU()来返回自己电脑中的物理处理器个数,而物理处理器的个数是和自己电脑的处理器挂钩的

// main方法
func main() {
    routine.GOMAXPROCS(2)
    fmt.Println(runtime.NumCPU()) // 20
    // 实例化计数器wg
	var wg sync.WaitGroup
    // 要运行两个goroutine函数
	wg.Add(2)
	go functions.Demo01(2, "the first goroutine!", &wg)
	go functions.Demo01(3, "the second goroutine!", &wg)
    // 等待两个goroutine运行完毕
	wg.Wait()
    // 执行完毕后再输出over!
	fmt.Println("over!")
}

​ 通过并行执行,我们就可以保证不同的协程是同时运行在不同的逻辑处理器当中,可以实行同时运行

有关Go语言入门12(协程 goroutine)的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  3. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  4. 7个大一C语言必学的程序 / C语言经典代码大全 - 2

    嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来

  5. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  6. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  7. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  8. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

  9. ruby - 如何保持我不常用的编程语言技能 - 2

    关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭11年前。Improvethisquestion我不经常使用ruby​​-通常它加起来相当于每两个月或更长时间编写一次脚本。我的大部分编程都是使用C++进行的,这与ruby​​有很大不同。由于我与ruby​​之间的差距如此之大,我总是忘记语言的基本方面(比如解析文本文件和其他简单的东西)。我想每天练习一些基本的东西,我想知道是否有一些我可以订阅的网站,并且会向我发送当天的Ruby问题或类似的东西。有人知道这样的站点/Internet服务吗?

  10. ruby-on-rails - 如果特定语言环境中缺少翻译,如何配置 i18n 以使用 en 语言环境? - 2

    如果特定语言环境中缺少翻译,如何配置i18n以使用en语言环境翻译?当前已插入翻译缺失消息。我正在使用RoR3.1。 最佳答案 找到相似的question这里是答案:#application.rb#railswillfallbacktoconfig.i18n.default_localetranslationconfig.i18n.fallbacks=true#railswillfallbacktoen,nomatterwhatissetasconfig.i18n.default_localeconfig.i18n.fallback

随机推荐