当前位置: 首页 > 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…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1 本教程使用零知标准板&#xff08;STM32F103RBT6&#xff09;通过I2C驱动ICM20948九轴传感器&#xff0c;实现姿态解算&#xff0c;并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化&#xff0c;适合嵌入式及物联网开发者。在基础驱动上新增…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...