11 Goroutine-并发与并行、阻塞与非阻塞

并发

顺序执行:按照事先计划好的顺序,执行完一个操作后,再执行下一个操作。

顺序执行效率不高的原因:

  • 每个操作由多个步骤组成,每个步骤所需要的时间长短不一,有些步骤可能相当耗时。
  • 顾客点菜需要时间,后厨做菜也需要时间,可否利用这些时间为更多顾客提供服务呢。

优化目标:减少不必要的闲置和等待,最大化处理机时间,提高工作效率

  • 当一个操作执行到某个相当耗时的步骤时,转而执行其它操作中相对不太耗时的步骤。
  • 待这些非耗时步骤完成后,之前那个耗时的步骤也完成了,再继续回到前一个操作中。

并发执行:没有固定的执行顺序,不等一个操作执行完,即开始下一个操作

并发与并行

并发一个行为主体同时执行多个操作。

并行多个行为主体同时执行多个操作。

浏览器中的并发

启用浏览器开发人员工具,打开任意可访问页面,可以看到浏览器并不是依次发出每一个请求,而是同时发出很多请求,以尽快渲染页面的每个组成部分。这样做的好处是页面的整体加载速度在用户看来非常之快。

阻塞与非阻塞

在实际编程中,有些函数的执行速度很,对于调用者而言几乎瞬间就返回了,这样的函数称为非阻塞函数。

但另一些函数的执行速度则可能非常缓,在调用者看来从调用到返回需要经历非常漫长的等待,甚至可能是永久的等待,这样的函数称为阻塞函数。

  • 在顺序模式中,阻塞的操作会导致其后的操作长期永远得不到执行,降低程序的性能。
  • 在并发模式中,阻塞的操作会和其它操作分属于不同的执行过程,快不必等慢,高性能。
// 顺序执行
// 在顺序模式中,阻塞的操作过程会导致其后的操作永远或长期得不到执行,降低程序的性能
package main
import ("fmt""time"
)
func proc(ch rune, ms time.Duration) {for {	// 死循环,模拟阻塞fmt.Printf("%c", ch)time.Sleep(ms * time.Millisecond)}
}
func main() {proc('-', 100)proc('+', 500)
}
// 打印输出:
// -------------------------

通过goroutine并发处理

Go语言通过Goroutine处理并发,为了使某个函数在独立的"线程"中执行,只需在调用该函数的时候使用关键字go。

  • go proc('-', 100)

将任何阻塞函数放在关键字go的后面执行:

  • 立即启动一个独立的"子线程",并在该"子线程"中执行阻塞函数中的代码。
  • 与此同时"父线程"从go中立即返回,并不等待阻塞函数返回,即"子线程"结束。
  • "父线程"在"子线程"执行阻塞函数的同时,执行该语句下面的操作。
  • go下面的操作和go后面的函数分别运行在父子两个独立"线程"中。
  • 阻塞函数执行完毕返回,"子线程"结束。
// 并发执行
// 在并发模式中,阻塞的操作过程运行于独立的"线程"之中,不会影响其它操作的执行,提高了程序的性能
package main
import ("fmt""time"
)
func proc(ch rune, ms time.Duration) {for {fmt.Printf("%c", ch)time.Sleep(ms * time.Millisecond)}
}
func main() {go proc('-', 100) // 每100ms,打印-proc('+', 500)		// 每500ms,打印+
}
// 打印输出:
// +-----+-----+-----+-----+ 

Goroutine与线程

Goroutine常被称作轻量级线程逻辑线程,它和真正的线程还是有区别的。

线程

Goroutine

调度

开销

线程由操作系统内核调度,每隔几毫秒,会有一个硬件时钟中断发送到CPU,CPU会调用一个调度器内核函数。该函数暂停当前正在运行的线程,把它的寄存器信息保存到内存中,查看线程列表并决定接下来运行哪一个线程,再从内存中恢复此线程的寄存器信息并执行之。这种线程调度需要一个完整的上下文切换,即保存一个线程的状态到内存,再从内存恢复另一个线程的状态,同时还要不断更新调度器的数据结构。某种意义上讲,这种操作还是相当耗时的。

Go语言程序运行时自带一个调度器,这个调度器使用一个称为一个M:N的调度技术,即将M个Goroutine调度到N个线程中,Go的调度器不由硬件时钟定期触发,而由特定的Go语言结构触发,也不需要在用户态和内核态之间来回切换,所以调度一个Goroutine比调度一个线程的开销要小得多。

栈空间

每个线程都有一个固定大小的栈内存,通常是2M字节,栈内存用于保存函数的参数、局部变量和返回地址。

Goroutine的栈内存是动态的,开始只有2K字节,而后随着程序的运行,再根据实际需要增大或缩小,最大可以到1G字节。

线程

标识

在大部分支持线程的操作系统中,每个线程都有一个唯一标识,通常是一个整数或者结构体,通过该标识可以为每个线程创建独立的全局存储空间,谓之线程局部存储。

Goroutine没有提供可被程序员访问的唯一标识,它是一种纯函数的理念。Go语言认为线程局部存储的滥用会导致一种不健康的超距作用,即函数的行为不仅取决于它的参数,还与执行它的线程有关。

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

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

相关文章

VectorDBBench在windows的调试

VectorDBBench在windows的调试 VectorDBBench是一款向量数据库基准测试工具,支持milvus、Zilliz Cloud、Elastic Search、Qdrant Cloud、Weaviate Cloud 、 PgVector、PgVectorRS等,可以测试其QPS、时延、recall。 VectorDBBench是一款使用python编写的…

深度学习模型在OCR中的可解释性问题与提升探讨

摘要: 随着深度学习技术在光学字符识别(OCR)领域的广泛应用,人们对深度学习模型的可解释性问题日益关注。本文将探讨OCR中深度学习模型的可解释性概念及其作用,以及如何提高可解释性,使其在实际应用中更可…

Java 零基础入门学习(小白也能看懂!)

📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更…

第16篇:JTAG UART IP应用<三>

Q:如何通过HAL API函数库访问JTAG UART? A:Quartus硬件工程以及Platform Designer系统也和第一个Nios II工程--Hello_World的Quartus硬件工程一样。 Nios II软件工程对应的C程序调用HAL API函数,如open用于打开和创建文件&#…

使用YOLOv9训练和测试自己的数据集

任务:检测舌头上的裂纹和齿痕 已经有了labelme标注的数据集,并且转为了coco格式 参考: 详细!正确!COCO数据集(.json)训练格式转换成YOLO格式(.txt)_coco数据集的train…

服务器数据恢复—服务器raid常见故障表现原因解决方案

RAID(磁盘阵列)是一种将多块物理硬盘整合成一个虚拟存储的技术,raid模块相当于一个存储管理的中间层,上层接收并执行操作系统及文件系统的数据读写指令,下层管理数据在各个物理硬盘上的存储及读写。相对于单独的物理硬…

2023年全国青少年人工智能创新挑战赛真题

为了大家备考2024年第七届全国青少年人工智能创新挑战赛,今天分享2023年第6届全国青少年人工智能创新挑战赛C信息学专项真题,图形化编程及Python编程基本大同小异,参考6547网的Python及图形化编程题库。 一、单项选择题(共 15 题,每题 2 分,共…

vscode中使用conda虚拟环境

每一次配置环境,真的巨烦,网上的资料一堆还得一个个尝试,遂进行整理 1.准备安装好Anaconda 附带一篇测试教程,安装anaconda 2.准备安装vscode 安装地址:Visual Studio Code 3.创建Conda环境 搜索框搜索Anaconda…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《计及液态空气储能与综合需求响应的综合能源系统低碳经济调度》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

HTML静态网页成品作业(HTML+CSS)——游戏阴阳师介绍网页(4个页面)

🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有4个页面。 二、作品演示 三、代…

JAVASE2

封装的步骤: 1、所有属性私有化,使用private关键字进行修饰,private表示私有的,修饰的所有数据只能在本类中访问 2、对外提供简单入口:比如说被private修饰的成员变量,在其他类中只能通过getXxx/setXxx方法…

网络风暴:揭秘DDoS攻击的幕后黑手

在数字化时代的浪潮中,网络攻击已成为一种新型的战争手段。其中,分布式拒绝服务攻击(DDoS)以其强大的破坏力和隐蔽性,成为网络安全领域的一大挑战。DDoS攻击通过发动海量的恶意流量,如同狂风暴雨般席卷目标…

如何设置远程桌面连接?

远程桌面连接是一种方便快捷的远程访问工具,可以帮助用户在不同地区间快速组建局域网,解决复杂网络环境下的远程连接问题。本文将针对使用远程桌面连接的操作步骤进行详细介绍,以帮助大家快速上手。 步骤一:下载并安装远程桌面连接…

各种情况下的线缆大小选择

开口线鼻子和导线对应大小 开口铜鼻子对应线径大小 变压器容量对应高压侧电流大小 开关电流线缆功率对照表 家庭/工业最常用电线铜线电流承载功率 电工常用名词对应符号 导线面积承载的安全载流量及允许负荷对照表 漏电保护器选择参考表 电动机功率换算电流 电机功…

代码随想录——最大二叉树(Leetcode654)

题目链接 递归 二叉树 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode rig…

.NET 轻量级、高效任务调度器:ScheduleTask

前言 至于任务调度这个基础功能,重要性不言而喻,大多数业务系统都会用到,世面上有很多成熟的三方库比如Quartz,Hangfire,Coravel 这里我们不讨论三方的库如何使用 而是从0开始自己制作一个简易的任务调度,如果只是到分钟级别的粒…

全能集成开发平台Team·IDE

三甲医院的床位太难等了。反正也是小手术,老苏周五在附近找了家二甲医院,幸运的是,门诊迅速为我开具了入院证。周六早晨就接受了手术,周日挂了一天水,周一下午就出院了。准备在家先休息两天。 2~4 周之后把支架取出来…

阿里云海外视频安全的DRM加密

随着科技的进步,视频以直播或录播的形式陆续开展海外市场,从而也衍生出内容安全的问题,阿里云在这方面提供了完善的内容安全保护机制,适用于不同的场景,如在视频安全提供DRM加 由图可以了解到阿里云保护直播安全的方法…

【软件设计师】程序语言

1.程序设计语言基本概念 1.1 低级语言与高级语言 低级语言:机器语言和汇编语言称为低级语言 机器语言指0.,1组成的机器指令序列 汇编语言指用符号表示指令的语言,如MOV AX,2 高级语言:从人类的逻辑角度出发&#xff0…

numpy-mkl的下载地址

不要使用pip3直接在终端安装,因为pip3默安装的是numpy,而不是numpymkl。 采用在第三方库中手动下载后,再安装的方式。 第三方库网址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy 如果不能进入就可以选择去git里面&#x…