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

【gogogo专栏】golang并发编程

golang并发编程

  • 并发编程的工具
    • goroutine介绍
      • 协程管理器sync.WaitGroup
    • channel介绍
      • readChannel和writeChannel
      • close的用法
      • select的用法
  • 通讯示例
  • 总结

并发编程的工具

在golang中,并发编程是比较简单的,不像java中那么麻烦,golang天然的支持协程(线程)的管理,通常用goroutine和channel来管理go的并发编程。

goroutine介绍

goroutine在go语言中叫做协程,相当于java中线程的概念,使用起来也非常简单,在方法前面加个go就行了。

go Run() 例如这样就是开启一个新的协程去跑Run方法

协程管理器sync.WaitGroup

在使用协程时,如果主线程结束的时候,我们并不能知道协程里面发生了什么,也无法控制它,因此引入了sync.WaitGroup,来控制协程。
我们来看以下这个例子,在协程启动的时候开启了一个协程WaitGroup,当Add里面有数字的时候,当数字减到0才能结束。

func main() {var wg sync.WaitGroupwg.Add(1)go Run(&wg)wg.Wait()
}func Run(wg *sync.WaitGroup) {fmt.Println("我跑起来了")wg.Done()
}

我们首先测试一下方法

wg.Add(1) ===> 输出结果:我跑起来了
wg.Add(0) ===> 输出结果:空
wg.Add(2) ===> 输出结果:我跑起来了 fatal error: all goroutines are asleep - deadlock!

我们可以看到这里有个报错,在 main 函数中使用了 wg.Wait() 来等待两个协程完成任务,但是在 Run 函数中,你只是调用了 wg.Done() 来通知 WaitGroup 任务完成,但是没有关闭等待。
因此推荐以下这种写法,比较安全,保证最终关闭等待。

func main() {var wg sync.WaitGroupwg.Add(2)go func() {defer wg.Done()Run()}()go func() {defer wg.Done()Run()}()wg.Wait()
}func Run() {fmt.Println("我跑起来了")
}

channel介绍

channel是用来负责协程之间的通信的,可以理解为一个管道,我们首先举一个最简单的例子,箭头表示读取,这样就表示往管道里面读入和获取一个数了。

func main() {c1 := make(chan int, 1)c1 <- 1fmt.Println(<-c1)
}

c1 := make(chan int, 1) 这里的1代表缓冲区的容量,当有缓冲区的时候,存入数据会预先存进缓冲区,当需要的时候再取出。当c1 := make(chan int) 这样写的时候,则代表没有容量,写入的时候会阻塞,除非有其他goroutine进行消费,否则无法执行下一步操作。

因此调用下面这个方法则会造成死锁。

func main() {c1 := make(chan int)c1 <- 1fmt.Println(<-c1)
}

但是如果是异步执行的话则可以正常执行获取,因为这个写入的操作跑到另一个cpu线程(时间分片)上去了,不会对主线程造成阻塞,当主线程去获取这个值的时候,则可以顺利拿到。

func main() {c1 := make(chan int)go func() {c1 <- 1}()fmt.Println(<-c1)
}

下面我们再来看看缓冲区这个概念,以下面这段代码为例,无缓冲区时,向channel中存入则阻塞,有缓冲区时更像一种生产者消费者模型,充满缓冲区才阻塞。

func main() {//c1 := make(chan int)//c1 := make(chan int, 5)c1 := make(chan int, 10)go func() {for i := 0; i < 10; i++ {c1 <- i}}()for i := 0; i < 10; i++ {time.Sleep(time.Second)fmt.Println(<-c1)}
}

我们在这里打上断点可以很明显的看到变化。
在这里插入图片描述

readChannel和writeChannel

在channel中可以定义可读和可写channel

func main() {c1 := make(chan int, 5)var read <-chan int = c1var write chan<- int = c1write <- 1fmt.Println(<-read)
}

close的用法

close可以关闭一个channel,使其无法往里面写,但是仍然可以往里面读。

func main() {c1 := make(chan int, 5)c1 <- 1c1 <- 2c1 <- 3c1 <- 4c1 <- 5close(c1)fmt.Println(<-c1)fmt.Println(<-c1)fmt.Println(<-c1)fmt.Println(<-c1)fmt.Println(<-c1)
}

此时不用close也是可以执行的,但是当我们使用循环取的时候,必须要用close。

func main() {c1 := make(chan int, 5)c1 <- 1c1 <- 2c1 <- 3c1 <- 4c1 <- 5close(c1)for v := range c1 {fmt.Println(v)}
}

select的用法

我们以一下代码为例

func main() {c1 := make(chan int, 1)c2 := make(chan int, 1)c3 := make(chan int, 1)c1 <- 1c2 <- 1c3 <- 1select {case <-c1:fmt.Println("c1")case <-c2:fmt.Println("c2")case <-c3:fmt.Println("c3")default:fmt.Println("都没执行")}
}

使用select可以将能执行的都执行,比如上面的代码执行顺序就是三个case随机一个或全部执行。

通讯示例

func main() {var wg sync.WaitGroupwg.Add(2) // 增加等待组计数器,表示有两个协程需要等待ch := make(chan int) // 创建整数类型的通道go producer(ch, &wg) // 启动生产者协程go consumer(ch, &wg) // 启动消费者协程wg.Wait() // 等待所有协程执行完毕
}func producer(ch chan int, wg *sync.WaitGroup) {defer wg.Done()for i := 0; i < 10; i++ {fmt.Println("Produced:", i)ch <- i}close(ch) // 关闭通道,表示生产者完成生产
}func consumer(ch chan int, wg *sync.WaitGroup) {defer wg.Done()for data := range ch {fmt.Println("Consumed:", data)}
}

我们可以通过这种方式实现一个简单的生产者消费者模型来实现线程交互。

总结

在go语言中,我们完全可以通过goroutine和channel实现线程之间的通讯,来实现协程之间协调。

相关文章:

【gogogo专栏】golang并发编程

golang并发编程 并发编程的工具goroutine介绍协程管理器sync.WaitGroup channel介绍readChannel和writeChannelclose的用法select的用法 通讯示例总结 并发编程的工具 在golang中&#xff0c;并发编程是比较简单的&#xff0c;不像java中那么麻烦&#xff0c;golang天然的支持协…...

深入理解JVM虚拟机第二十二篇:详解JVM当中与操作数栈相关的字节码指令

大神链接&#xff1a;作者有幸结识技术大神孙哥为好友&#xff0c;获益匪浅。现在把孙哥视频分享给大家。 孙哥链接&#xff1a;孙哥个人主页 作者简介&#xff1a;一个颜值99分&#xff0c;只比孙哥差一点的程序员 本专栏简介&#xff1a;话不多说&#xff0c;让我们一起干翻J…...

Vue报错解决Error in v-on handler: “Error: 无效的节点选择器:#div1“

因为我们在创建元素之前用了#div1"所有它会报错&#xff0c;解决方案简单粗暴咱们直接用 setTimeout(createEdit, 1)解决问题了 原理&#xff1a;vue的虚拟dom创建完成以后再调用真是dom就没啥问题 function createEdit() {const editor new E(#div1)editor.config.hei…...

R | R包安装报错-github连接速度慢或无法访问 | metaboanalystR | Retip | rJava安装

R | R包安装报错-github连接速度慢或无法访问 | metaboanalystR | Retip | rJava安装 一、metaboanalystR 安装1.1 Bioconductor报错&#xff0c;无网络连接1.2 github520-修改hosts文件 二、retip安装2.1 rJava包加载报错及安装2.2 安装Retip包 三、从Bioconductor安装Rdisop报…...

博阳精讯、凡得科技访问上海斯歌:共探BPM流程服务新高地

10月27日下午&#xff0c;来自博阳精讯、凡得科技的流程领域专家、领导一行参观访问了上海斯歌总部。三方举行了深度交流会谈&#xff0c;分享了彼此对流程领域的前沿洞察和技术实践&#xff0c;共同探索了BPM流程服务科技力与价值力的新高地。 本次研讨会上&#xff0c;博阳精…...

响应式艺术作品展示前端html网站模板源码

响应式艺术作品展示网站模板是一款适合各种艺术作品在线展示的响应式网站模板下载。提示&#xff1a;本模板调用到谷歌字体库&#xff0c;可能会出现页面打开比较缓慢。 转载自 https://www.qnziyw.cn/wysc/qdmb/23778.html...

大语言模型(LLM)综述(六):大型语言模型的基准和评估

A Survey of Large Language Models 前言7 CAPACITY AND EVALUATION7.1 基本能力7.1.1 语言生成7.1.2 知识利用7.1.3 复杂推理 7.2 高级能力7.2.1 人类对齐7.2.2 与外部环境的交互7.2.3 工具操作 7.3 基准和评估方法7.3.1 综合评价基准7.3.2 评估方法 7.4 实证评估7.4.1 实验设…...

【Python自学笔记】Flask调教方法Internel Server Error

收到老师的小组作业任务说是写一个自动报告程序&#xff0c;用PythonSQLiteHTML实现&#xff0c;好吧。 前面没什么问题&#xff0c;打开VSCode&#xff0c;连数据库读数据处理可视化模板拼凑&#xff0c;最后调用Flask框架出网页报告的时候总报错连接不了。 但换了jinjia2的渲…...

【AICFD案例教程】汽车外气动-AI加速

AICFD是由天洑软件自主研发的通用智能热流体仿真软件&#xff0c;用于高效解决能源动力、船舶海洋、电子设备和车辆运载等领域复杂的流动和传热问题。软件涵盖了从建模、仿真到结果处理完整仿真分析流程&#xff0c;帮助工业企业建立设计、仿真和优化相结合的一体化流程&#x…...

P1547 [USACO05MAR] Out of Hay S 题解

文章目录 题目描述输入格式输出格式样例样例输入样例输出 完整代码 题目描述 Bessie 计划调查 N N N&#xff08; 2 ≤ N ≤ 2 000 2 \leq N \leq 2\,000 2≤N≤2000&#xff09;个农场的干草情况&#xff0c;它从 1 1 1 号农场出发。农场之间总共有 M M M&#xff08; 1 ≤…...

2023.11.10联测总结

T 1 T1 T1求的是有多少个区间的异或和是 k k k的因子&#xff0c; n , k ≤ 1 0 5 n,k \leq 10^5 n,k≤105。 这道题用前缀和维护一下&#xff0c;暴力枚举所有区间就有 80 80 80分。 有一瞬间想过枚举因数&#xff0c;但是脑抽以为要 O ( n ) \mathcal O(n) O(n)枚举&#x…...

C++:list?自己模拟实现!

目录 1.list的模拟实现 1.1 成员变量和节点 1.2 迭代器实现 1.2.1 非const的迭代器 1.2.2 const的迭代器 1.2.3 一个模板实现 const 与 非const 迭代器 1.3 增删改查的实现 1.4 拷贝构造函数&#xff0c;析构函数与赋值运算符重载 1.5 泛型编程实现打印 2. list 反…...

layui table合并相同的列

table.render({elem: #samples,url: /index/Develorderss/samplelists?od_idod_id //数据接口,page: { //支持传入 laypage 组件的所有参数&#xff08;某些参数除外&#xff0c;如&#xff1a;jump/elem&#xff09; - 详见文档layout: [prev, page, next, count,skip,limit]…...

【Spring】SpringBoot配置文件

SpringBoot配置文件 配置文件作用SpringBoot配置文件配置文件快速入手配置文件的格式properties配置文件说明基本语法读取配置文件properties缺点分析 yml配置文件说明yml基本语法yml使用进阶yml配置读取配置对象配置集合配置Mapyml优缺点 配置文件作用 计算机上有数以千计的配…...

python批量下载txt文件中链接的数据

python下载txt文件中链接的数据,以gimms ndvi3g下载为例 官方下载网址:https://www.ncei.noaa.gov/data/land-normalized-difference-vegetation-index/access/ 选择下载2020年数据为例: 网址:Index of /data/land-normalized-difference-vegetation-index/access/2020…...

stm32 Bootloader设计(YModem协议)

stm32 Bootloader设计&#xff08;YModem协议&#xff09; Chapter1 stm32 Bootloader设计(YModem协议)YModem协议&#xff1a;STM32 Bootloader软件设计STM32 Bootloader使用方法准备工作stm32 Bootloader修改&#xff1a;stm32目标板程序.bin偏移地址修改&#xff1a; Chapt…...

竞赛 题目: 基于深度学习的疲劳驾驶检测 深度学习

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…...

ubuntu 16.04.5 安装 vivado 2019.1 完整编译AD9361的环境

一、前期安装 1、安装ncurses库&#xff08;已经包含了&#xff0c;其他的os需要安装&#xff09; sudo apt install libncurses5二、安装 sudo ./xsetup使用lic进行激活。 三、安装后 输入指令 sudo gedit ~/.bashrc 末尾添加 source /opt/Xilinx/Vivado/2019.1/setti…...

Zotero详细功能补充!熟练使用!【进阶版,持续更新】

Zotero安装请参见文章Zotero安装 1.改变条目文件夹 如果直接选择条目直接进行移动&#xff0c;能移动成功&#xff0c;但是原来文件夹和目标文件夹都会存在&#xff0c;实际是复制&#xff01; 如果只想保留在一个文件夹里面&#xff0c;可以选中条目&#xff0c;右击-从分…...

【Windows】Windows系统常用命令大全

现实生活中&#xff0c;对电脑越熟悉懂得的快捷命令就越多。例如我们日常遇到的比较方便办公技巧&#xff0c;用快捷命令调用工具&#xff1a;调用计算器&#xff0c;Win键R&#xff0c;输入calc&#xff0c;回车&#xff0c;计算器界面弹出来&#xff1b; 调用记事本&#xff…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...