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

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

LLMs 系列实操科普(1)

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

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...