WordPress自动建站/百度识图网页版在线使用
并发编程在当前软件领域是一个非常重要的概念,随着CPU等硬件的发展,我们无一例外的想让我们的程序运行的快一点、再快一点。Go语言在语言层面天生支持并发,充分利用现代CPU的多核优势,这也是Go语言能够大范围流行的一个很重要的原因。
并且在云的大放光彩的今天。想要支持分布式的,并且并发。那么go就是不二人选。
当然对于并发来说,一章是难说完的
文章目录
- 基本概念
- 串行、并发与并行
- 进程、线程和协程
- 并发模型
- goroutine(正文)
- go关键字
- 启动单个goroutine
- 启动多个goroutine
- 内存分配机制:动态栈
- goroutine调度
基本概念
串行、并发与并行
吃糖葫芦:
-
串行
:我们先吃最上面的,一块一块的吃,然后慢慢吃完 -
并发
:同一时间段内执行多个任务(你吃的比较快,在同一时间,别人吃一个,你可以吃两个或者更多)。 -
并行
:同一时刻执行多个任务(你叫朋友一起帮你吃)。
进程、线程和协程
-
进程(process)
:程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。 -
线程(thread)
:操作系统基于进程开启的轻量级进程,是操作系统调度执行的最小单位。 -
协程(coroutine)
:非操作系统提供而是由用户自行创建和控制的用户态‘线程’,比线程更轻量级。
并发模型
行业内,将如何实现并发编程总结归纳为各式各样的并发模型,常见的并发模型有以下几种:
- 线程&锁模型
- Actor模型
- CSP模型
- Fork&Join模型
Go语言中的并发程序主要是通过基于CSP(communicating sequential processes)
的goroutine
和channel
来实现,当然也支持
使用传统的多线程共享内存
的并发方式(java 的方式,也就是线程&锁模型
)。
goroutine(正文)
Goroutine 是 Go 语言支持并发的核心,在一个Go程序中同时创建成百上千个goroutine是非常普遍的,一个goroutine会以一个很小的栈
开始其生命周期,一般只需要2KB
。
区别于操作系统线程
由系统内核进行调度
, goroutine 是由Go运行时(runtime)负责调度
例如
Go运行时会智能地将 m个goroutine 合理地分配给n个操作系统线程,实现类似m:n
的调度机制,不再需要
Go开发者自行在代码层面维护一个线程池
。
在Go语言编程中你不需要去自己写进程、线程、协程,你的技能包里只有一个技能——goroutine。(这个就比较方便)
当你需要让某个任务并发执行的时候,你只需要把这个任务包装成一个函数,开启一个 goroutine 去执行这个函数就可以了,就是这么简单粗暴。
其实说到这个我说一下体外话。编程语言趋于简单易操作化已经非常明显了。从市场的角度来说。编程语言的已经从院士–》博士–》–》研究生–》本科生–》专科生–》中学生—》小学生–》幼儿园了。几乎随着时间的变化,越来越来下放。学习成本越来越低。
也就是说,对于编程语言来说。如何扩大行业人选来说。越简单,去学习的人越多,当然这是在这个编程语言有特点的来说。如果没有优势,然后去学,要我说这样纯属扯淡。为了简单而失去编程的本质,就有问题了。
不扯了。。。。。
go关键字
Go语言中使用 goroutine 非常简单,只需要在函数或方法调用前加上go关键字就可以创建一个goroutine
,从而让该函数或方法在新创建的 goroutine
中执行。
go f() // 创建一个新的 goroutine 运行函数f
匿名函数也支持使用go关键字
创建 goroutine
去执行
go func(){// ...
}()
一个 goroutine
必定对应一个函数/方法
,可以创建多个 goroutine
去执行相同的函数/方法
。
记住在这个大括号后的小括号中填入的传入方法的参数
启动单个goroutine
启动 goroutine 的方式非常简单,只需要在调用函数(普通函数和匿名函数)前
加上一个go关键字
。
先实现一个串行例子
package mainimport ("fmt"
)func hello() {fmt.Println("hello")
}func main() {hello()fmt.Println("你好")
}
根据代码逻辑就是从上至下执行。
ok我们试一下加上关键字go,启动一个 goroutine 去执行 hello 这个函数。
package mainimport ("fmt""time"
)func hello() {fmt.Println("hello")
}func main() {go hello()fmt.Println("你好")
}
打印的结果居然是:
ok出bug了。为什么呢?
原因
其实在 Go 程序
启动时,Go 程序就会为 main 函数创建一个默认的 goroutine
。
在上面的代码中我们在 main 函数中
使用 go 关键字
创建了另外
一个 goroutine 去执行 hello 函数
,而此时 main goroutine
还在继续往下执行,我们的程序中此时存在两个并发执行的 goroutine。
当 main 函数结束时整个程序也就结束了
,同时 main goroutine 也结束了,所有由 main goroutine 创建的 goroutine 也会一同退出。
也就是说我们的 main 函数退出太快,另外一个 goroutine 中的函数还未执行完程序就退出了,导致未打印出“hello”。
所以我们要想办法让 main 函数‘“等一等”将在另一个 goroutine 中运行的 hello 函数。
其中最简单粗暴的方式就是在 main 函数中“time.Sleep”一秒钟了(其实存在等待函数的)
package mainimport ("fmt""time"
)func hello() {fmt.Println("hello")
}func main() {go hello()fmt.Println("你好")time.Sleep(time.Second)
}
此时就成功了。但是者子其中有一个问题发现没有,为什么会先打印 “你好” 呢?
因为在程序中创建 goroutine 执行函数需要一定的开销,而与此同时 main 函数所在的 goroutine 是继续执行的。
上面说了,这么粗暴的使用。是非常不雅观的。
Go 语言中通过sync包
为我们提供了一些常用的并发原语。下一章说如何用。
这里我们先说, sync 包中的WaitGroup。
当你并不关心并发操作的结果
或者有其它方式收集并发操作的结果时
,WaitGroup是实现等待一组并发操作完成的好方法。
例子:
package mainimport ("fmt""sync"
)// 声明全局等待组变量
var wg sync.WaitGroupfunc hello() {fmt.Println("hello")wg.Done() // 告知当前goroutine完成
}func main() {wg.Add(1) // 登记1个goroutinego hello()fmt.Println("你好")wg.Wait() // 阻塞等待登记的goroutine完成
}
将代码编译后再执行,得到的输出结果和之前一致,但是这一次程序不再会有多余的停顿,hello goroutine 执行完毕后程序直接退出。
启动多个goroutine
单个并发只能说是小试牛刀,多个并发才是业务该有的逻辑。
package mainimport ("fmt""sync"
)var wg sync.WaitGroupfunc hello(i int) {defer wg.Done() // goroutine结束就登记-1fmt.Println("hello", i)
}
func main() {for i := 0; i < 10; i++ {wg.Add(1) // 启动一个goroutine就登记+1go hello(i)}wg.Wait() // 等待所有登记的goroutine都结束
}
多次执行上面的代码会发现每次终端上打印数字的顺序都不一致。这是因为10个 goroutine 是并发执行的,而 goroutine 的调度是随机的。
但是看了这个,大家对于这个defer
起的作用肯定是有疑问的。
在很早之前就说过这个关键字。这里我认为有必要在给大家说一说。这个关键字很重要,它的应用场景很多。在go中最主要的为三个,一个是同步并发
(这里的主要作用),一个是搭配recover 处理异常
,一个是关闭资源
。这三个应用场景非常常见。而有这些场景,离不开它本有的特性。-----------延迟调用
,简单而言就是最后执行。
内存分配机制:动态栈
操作系统的线程一般都有固定的栈内存(通常为2MB
),而 Go 语言中的 goroutine 非常轻量级,一个 goroutine
的初始栈空间
很小(一般为2KB
),所以在 Go 语言中一次创建数万个 goroutine 也是可能的。并且 goroutine 的栈不是固定的,可以根据需要动态地增大或缩小, Go 的 runtime 会自动为 goroutine 分配合适的栈空间
goroutine调度
操作系统内核在调度时
- 会挂起当前正在执行的线程并将寄存器中的内容保存到内存中
- 选出接下来要执行的线程并从内存中恢复该线程的寄存器信息
- 恢复执行该线程的现场并开始执行线程
从一个线程切换到另一个线程需要完整的上下文切换。因为可能需要多次内存访问,索引这个切换上下文的操作开销较大,会增加运行的cpu周期。
goroutine 的调度
goroutine 的调度是Go语言运行时(runtime)层面的实现,是完全由 Go 语言本身实现的一套调度系统——go scheduler
。它的作用是按照一定的规则将所有的 goroutine 调度到操作系统线程上执行。
目前 Go 语言的调度器采用的是 GPM 调度模型。
-
G:表示 goroutine
,每执行一次go f()
就创建一个 G,包含要执行的函数和上下文信息。 -
全局队列(Global Queue)
:存放等待运行的 G。 -
P
:表示goroutine 执行所需的资源
,最多有GOMAXPROCS
个。 -
P 的本地队列
:同全局队列类似,存放的也是等待运行的G,存的数量有限,不超过256个
。新建 G 时,G 优先加入到 P 的本地队列,如果本地队列满了会批量
移动部分 G 到全局队列。 -
M
:线程想运行任务就得获取 P,从 P 的本地队列获取 G,当 P 的本地队列为空时,M 也会尝试从全局队列或其他 P 的本地队列获取 G。M 运行 G,G 执行之后,M 会从 P 获取下一个 G,不断重复下去。 -
Goroutine 调度器
和操作系统调度器
是通过 M 结合起来的,每个 M 都代表了1个内核线程,操作系统调度器负责把内核线程分配到 CPU 的核上执行。 -
GOMAXPROCS
:Go运行时的调度器使用GOMAXPROCS参数来确定需要使用多少个 OS 线程来同时执行 Go 代码。
单从线程调度讲,
Go语言
相比起其他语言的优势在于OS线程
是由OS内核
来调度的, goroutine 则是由Go运行时(runtime)自己的调度器调度的,完全是在用户态下完成的, 不涉及内核态与用户态
之间的频繁切换,包括内存的分配与释放,都是在用户态维护着一块大的内存池
, 不直接调用系统的malloc函数(除非内存池需要改变),成本比调度OS线程低很多。 另一方面充分利用
了多核的硬件资源,近似的把若干goroutine均分在物理线程
上, 再加上本身 goroutine 的超轻量级,以上种种特性保证了 goroutine 调度方面的性能。
默认值是机器上的 CPU 核心数。例如在一个 8 核心的机器上,GOMAXPROCS 默认为 8。
Go语言中可以通过runtime.GOMAXPROCS函数设置当前程序并发时占用的 CPU逻辑核心数。
相关文章:

GoLong的学习之路(二十一)进阶,语法之并发(go最重要的特点)(协程的主要用法)
并发编程在当前软件领域是一个非常重要的概念,随着CPU等硬件的发展,我们无一例外的想让我们的程序运行的快一点、再快一点。Go语言在语言层面天生支持并发,充分利用现代CPU的多核优势,这也是Go语言能够大范围流行的一个很重要的原…...

加快网站收录 3小时百度收录新站方法
加快网站收录 3小时百度收录新站方法 3小时百度收录新站方法说起来大家可能不相信,但这确实是真实的(该方法是通过技术提交,让百度快速抓取收录您的网站,不管你网站有没有备案,都能在短时间内被收录,要是你的网站迟迟不…...

GPT实战系列-ChatGLM3本地部署CUDA11+1080Ti+显卡24G实战方案
目录 一、ChatGLM3 模型 二、资源需求 三、部署安装 配置环境 安装过程 低成本配置部署方案 四、启动 ChatGLM3 五、功能测试 新鲜出炉,国产 GPT 版本迭代更新啦~清华团队刚刚发布ChatGLM3,恰逢云栖大会前百川也发布Baichuan2-192K,一…...

图片怎么转换成pdf?
图片怎么转换成pdf?图片可以转换成PDF格式文档吗?当然是可以的呀,当图片转换成PDF文件类型时,我们就会发现图片更加方便的打开分享和传播,而且还可以更加安全的保证我们的图片所有性。我们知道PDF文档是可以加密的&…...

【源码】医学影像PACS实现三维影像后处理等功能
医学影像诊断技术近年来取得了快速发展,包括高性能的影像检查设备的临床应用和数字信息技术的图像显示、存储、传输、处理、识别,这些技术使得计算机辅助检测和诊断成为可能,同时人工智能影像诊断也进入了人们的视野。这些技术进步提高了疾病…...

DOCTYPE是什么,有何作用、 使用方式、渲染模式、严格模式和怪异模式的区别?
前言 持续学习总结输出中,今天分享的是DOCTYPE是什么,有何作用、 使用方式、渲染模式、严格模式和怪异模式的区别。 DOCTYPE是什么,有何作用? DOCTYPE是HTML5的文档声明,通过它可以告诉浏览器,使用那个H…...

Go语言实现HTTP正向代理
文章目录 前言实现思路代码实现 前言 正向代理(Forward Proxy)是一种代理服务器的部署方式,它位于客户端和目标服务器之间,代表客户端向目标服务器发送请求。正向代理可以用来隐藏客户端的真实身份,以及在不同网络环境…...

第11章_数据处理之增删改
文章目录 1 插入数据1.1 实际问题1.2 方式 1:VALUES的方式添加1.3 方式2:将查询结果插入到表中演示代码 2 更新数据演示代码 3 删除数据演示代码 4 MySQL8新特性:计算列演示代码 5 综合案例课后练习 1 插入数据 1.1 实际问题 解决方式&#…...

数据时代的新引擎:数据治理与开发,揭秘数据领域的黄金机遇!
文章目录 一、数据时代的需求二、数据治理与开发三、案例分析四、黄金机遇《数据要素安全流通》《Python数据挖掘:入门、进阶与实用案例分析》《数据保护:工作负载的可恢复性 》《Data Mesh权威指南》《分布式统一大数据虚拟文件系统 Alluxio原理、技术与…...

使用 Golang 实现基于时间的一次性密码 TOTP
上篇文章详细讲解了一次性密码 OTP 相关的知识,基于时间的一次性密码 TOTP 是 OTP 的一种实现方式。这种方法的优点是不依赖网络,因此即使在没有网络的情况下,用户也可以生成密码。所以这种方式被许多流行的网站使用到双因子或多因子认证中&a…...

微服务之Nacos配置管理
文章目录 一、统一配置管理Nacos操作二、统一配置管理java操作1.引入依赖2.创建配置文件3.测试4.总结 三、Nacos配置自动更新1.添加注解RefreshScope2.使用ConfigurationProperties注解3.总结 四、Nacos多环境配置共享1.配置文件2.多种配置的优先级3.总结 一、统一配置管理Naco…...

PySpark 优雅的解决依赖包管理
背景 平台所有的Spark任务都是采用Spark on yarn cluster的模式进行任务提交的,driver和executor随机分配在集群的各个节点,pySpark 由于python语言的性质,所以pySpark项目的依赖注定不能像java/scala项目那样把依赖打进jar包中轻松解决问题…...

UNI-APP_获取手机品牌
在uni-app中,使用uni.getSystemInfoSync().brand可以获取设备的品牌信息。根据不同设备的品牌,uni.getSystemInfoSync().brand可能返回以下一些常见值 “Apple” - 苹果 “Samsung” - 三星 “Huawei” - 华为 “Xiaomi” - 小米 “OPPO” - OPPO “Vivo…...

新登录接口独立版变现宝升级版知识付费小程序-多领域素材资源知识变现营销系统
源码简介: 资源入口 点击进入 源码亲测无bug,含前后端源码,非线传,修复最新登录接口 梦想贩卖机升级版,变现宝吸取了资源变现类产品的很多优点,摒弃了那些无关紧要的东西,使本产品在运营和变现…...

「掌握创意,释放想象」——Photoshop 2023,你的无限可能!
Adobe Photoshop 2023(PS2023) 来了,全世界数以百万计的设计师、摄影师和艺术家使用 Photoshop 将不可能变为可能。从海报到包装,从基本的横幅到漂亮的网站,从令人难忘的徽标到引人注目的图标,Photoshop 2023让创意世界不断前进。借助直观的工…...

SQLSugar查询返回DataTable
SQLSugar是一个用于执行SQL查询的C#库,它提供了简单易用的API接口来执行SQL查询。要查询返回DataTable,可以使用SQLSugar的QueryHelper类。 以下是一个示例代码,展示了如何使用SQLSugar的QueryHelper类查询返回DataTable: 首先&…...

企业微信开启接收消息+验证URL有效性
企业微信开启接收消息验证URL有效性 📔 千寻简笔记介绍 千寻简笔记已开源,Gitee与GitHub搜索chihiro-notes,包含笔记源文件.md,以及PDF版本方便阅读,且是用了精美主题,阅读体验更佳,如果文章对…...

电脑访问不到在同网络的手机设备
手机连接了同网络的wifi,但是电脑ping不通手机的ip,这可能是路由出了问题,因为最终是走的mac地址,访问不了是因为电脑不知道手机的mac地址,则可以这样设置绑定mac地址,管理员权限启动cmd,然后执…...

国内MES系统应用研究报告:“企业MES应用现状”| 百世慧®
随着制造企业数字化转型需求的增强,工业软件的需求也不断被激发。 2022年,中国MES软件及服务市场规模实现23.8%的较高速增长。同时,随着工业互联网、MOM的兴起和不断发展,也推动着MES持续发展和不断迭代,如今MES向着更…...

C++模板元模板实战书籍讲解第一章题目讲解
目录 第一题 C代码示例 第二题 C代码示例 第三题 3.1 使用std::integral_constant模板类 3.2 使用std::conditional结合std::is_same判断 总结 第四题 C代码示例 第五题 C代码示例 第六题 C代码示例 第七题 C代码示例 总结 第一题 对于元函数来说,…...

Java在互联网网络安全中的应用(三)
目录 1. 互联网网络安全概述 2. Java的网络安全特性 3. 用Java加固网络应用 4. 安全传输 5. 安全框架和工具 6. 实际应用案例 7. 最佳实践和资源 目标 本次技术分享的目标是介绍Java技术在互联网网络安全中的应用,包括关键概念、最佳实践和实际案例。 1. 互…...

VMLogin如何解决跨境电商多账号管理难题?
做跨境电商的,比如亚马逊、eBay这些卖家。随着团队规模的扩大,或者多店铺运营,那么多个店铺多个账号管理就成为了一个困难。如何解决这个问题呢? 首先来看看很多电商卖家多账号管理会面临的问题 经营者通常需要同时管理多个市场…...

STM32创建工程步骤
以创建led工程为例: 新建一个led文件夹 新建一个以led命名的工程(用keil_uVision5)并添加三个组。 Library文件夹里放置库函数文件。 User: 点亮led灯的程序; 直接给寄存器赋值 调用库函数。 #include "stm…...

软考 系统架构设计师系列知识点之边缘计算(1)
所属章节: 第11章. 未来信息综合技术 第4节. 边缘计算概述 1. 边缘计算概念 在介绍边缘计算之前,有必要先介绍一下章鱼。章鱼就是用“边缘计算”来解决实际问题的。作为无脊椎动物中智商最高的一种动物,章鱼拥有巨量的神经元,但…...

vue:写一个数组box和list数组,在保留box数组中原有对象的同时,将list数组中每一个对象插入到box数组后面
前言:由于源码涉及到后端调用数据和一些无关的功能所以我就专门针对这个功能的代码,这样好方便理解。 1、在data中定义两个数组:box和list,并给它们初始化值 data() {return {box: [/*初始的box数组对象*/],list: [/*初始的list…...

Python教程:随机函数,开始猜英文单词的游戏
开始猜英文单词的游戏… 总计生命次数:3次 -----------游戏开始中…----------- ????请猜一个,4位数的单词:mafr 猜错了,再努力一下 -----------你还有2次生命------------ ma?&…...

Unit2_1:动态规划DP
文章目录 一、介绍二、0-1背包问题问题描述分析伪代码时间复杂度 三、钢条切割问题问题描述分析伪代码过程 四、矩阵链乘法背景性质分析案例伪代码 一、介绍 动态规划类似于分治法,它们都将一个问题划分为更小的子问题 最优子结构:问题的最优解包含子问题的最优解。DP适用的原…...

k8s提交spark应用消费kafka数据写入elasticsearch7
一、k8s集群环境 k8s 1.23版本,三个节点,容器运行时使用docker。 spark版本时3.3.3 k8s部署单节点的zookeeper、kafka、elasticsearch7 二、spark源码 https://download.csdn.net/download/TT1024167802/88509398 命令行提交方式 /opt/module/spark…...

linux傻瓜式安装Java环境及中间件
linux配置Java环境及中间件 1.傻瓜式安装Java1.下载2.追加3.刷新测试 2.傻瓜式安装docker1.docker卸载2.docker安装 3.Docker傻瓜式安装Redis1.傻瓜式安装安装并配置 4.Docker傻瓜式安装RabbitMQ5.Docker傻瓜式安装MySql1.拉取2.配置 6.傻瓜式安装Nacos1.官网下载nacos2.SQL文件…...

javascript中的new原理及实现
在js中,我们通过new运算符来创建一个对象,它是一个高频的操作。我们一般只是去用它,而很少关注它是如何实现的,它的工作机制是什么。 1 简介 本文介绍new的功能,用法,补充介绍了不加new也同样创建对象的方…...