go语言学习-并发编程(并发并行、线程协程、通道channel)

1、 概念

1.1 并发和并行

  • 并发:具有处理多个任务的能力 (是一个处理器在处理任务),cpu处理不同的任务会有时间错位,比如有A B 两个任务,某一时间段内在处理A任务,这时A任务需要停止运行一段时间,那么会切换到处理B任务,B任务停止运行,在切换处理A任务,只不过CPU处理快,看起来是同时处理多个任务。
  • 并行:同时执行多个任务的能力 (多个处理器) 。 比如3 个任务同时创建,cpu是3核的,那么3个处理器同时处理就是并行。

1.2 线程和协程

  • 线程(Thread)是计算机操作系统中程序运行时最小的执行单元,,是CPU调度的基本单元。一个线程可以理解为一个任务,都具有一个独立的控制流。(python和java一般会使用,一个线程占用内存8MB)
    在多线程编程中,可以将不同的任务或操作封装在不同的线程中,然后并发地执行这些任务,从而提高程序的性能和响应速度。
  • 协程(Coroutine)是一种轻量级的线程,也被称为用户态线程。与操作系统中的线程不同,协程由程序员自己管理调度。协程可以使用更少的资源,更快的创建和销毁,协程之间可以通过通道 (Channel) 进行通信和同步,避免了传统线程中锁等同步机制的开销和复杂性。(go使用的是协程,一个协程占用内存2KB)

2、go实现并发处理(GoRoutine)

GoRoutine实现: 只需要语句前添加go关键字即可。

注意: 主程序创建了协程以后,并不会等待所有的协程执行成功,需要主程序等待协程处理完成之后再去退出主程序

package mainimport ("fmt""time"
)// 做包子的函数
func makeBuns(filling string) {startTime := time.Now()fmt.Printf("%s馅开始的时间:%s", filling, startTime)fmt.Printf("开始做%s馅的包子\n", filling)// 1. 剁馅fmt.Printf("开始剁%s馅...\n", filling)// 2. 擀皮fmt.Println("开始擀皮...")time.Sleep(time.Second)// 3. 包包子fmt.Printf("开始包%s馅的包子...\n", filling)// 4. 蒸fmt.Printf("开始蒸%s馅的包子...\n", filling)cost := time.Since(startTime)fmt.Printf("%s馅共耗费的时间:%s", filling, cost)
}func main() {// go: goroutine并发处理,go 代码语句// 协程:2KB,线程:8MB// 不需要关心协程的底层逻辑、内存管理以及垃圾回收fillings := []string{"韭菜", "鸡蛋", "西葫芦"}for _, v := range fillings {// 包go makeBuns(v) // 它的时间会缩短吗?// 主程序创建了协程以后,并不会等待所有的协程执行成功,需要主程序等待协程处理完成之后再去退出主程序}time.Sleep(time.Second * 3) // 开发程序时不能用time.Sleep去等待!!!!
}

通过运行函数可以发现基本是同一时间执行的。
在这里插入图片描述

3、通道

3.1 基本语法

	// go的通道,也是一种类型。channel1 := make(chan 类型)就可以声明一个通道。这个通道可以理解为类似于共享文件的存储。//如果通道内没有数据,就会一直在此处阻塞,直到取到数据为止//通道打开之后需要通过closer关闭buns := make(chan string) //该通道只有一个位置buns := make(chan string,5) //该通道有五个位置channel <- "数据1" //发送数据data := <- channel //取数据defer close(buns) //等程序执行完后,关闭通道

3.2 阻塞原理

buns := make(chan string)//1、此时的通道默认只有一个位置,比如传入了值,那么下一个值传需要等待这个值被拿走,才可以有另外的一个数据进入。
//2、如果这个通道里面没有数据,也会被阻塞,等待有数据后,才可以继续往下走流程。

3.3 实践

package mainimport ("fmt""time"
)// 做包子的函数
func makeBuns(filling string, buns chan string) {fmt.Printf("开始做%s馅的包子\n", filling)// 1. 剁馅fmt.Printf("开始剁%s馅...\n", filling)// 2. 擀皮fmt.Println("开始擀皮...")time.Sleep(time.Second)// 3. 包包子fmt.Printf("开始包%s馅的包子...\n", filling)// 4. 蒸fmt.Printf("开始蒸%s馅的包子...\n", filling)// 5. 蒸好了time.Sleep(time.Second * 1)fmt.Printf("%s馅包子已经蒸好了,可以上菜了,蒸好的时间是:%s\n", filling, time.Now())// 6. 上菜// 在这个位置把蒸好的包子放到通道内buns <- fillingfmt.Printf("%s馅包子已经放在了上菜区,放置时间是:%s\n", filling, time.Now())
}// 上菜的函数
// func waiter(buns chan string) {
// 	// 把蒸好的包子拿出来去上菜
// 	bun := <-buns
// 	fmt.Printf("上菜:%s, 上菜时间:%s\n", bun, time.Now())
// }func main() {// go的通道,也是一种类型。channel1 := make(chan 类型)就可以声明一个通道// 发送数据: channel1 <- "数据1"// 取数据: data1 := <- channel1// 定义一个蒸好的包子的通道buns := make(chan string, 5)defer close(buns) //通道打开之后需要关闭// go: goroutine并发处理,go 代码语句// 协程:2KB,线程:8MB// 不需要关心协程的底层逻辑、内存管理以及垃圾回收// 做包子//fillings := []string{"韭菜", "鸡蛋", "西葫芦"}startTime := time.Now()for _, v := range fillings {// 包go makeBuns(v, buns) // 主程序创建了协程以后,并不会等待所有的协程执行成功,需要主程序等待协程处理完成之后再去退出主程序}//取包子for i := 0; i < len(fillings); i++ {// 在这里直接去包子// 把蒸好的包子拿出来去上菜time.Sleep(3 * time.Second)bun := <-buns // 如果通道内没有数据,就会一直在此处阻塞,直到取到数据为止fmt.Printf("上菜:%s, 上菜时间:%s\n", bun, time.Now())}cost := time.Since(startTime)fmt.Println("共耗费的时间:", cost)// time.Sleep(time.Second * 3) // 开发程序时不能用time.Sleep去等待!!!!}

3.4 Select处理多个channel通道

比如一个饭店多个菜系的师傅,然后相关菜系会放到对应的存放位置,然后服务员到对一个的位置取菜。

//select 基础语法select {case dish := <-chef1:fmt.Println("厨师chef1已经做好了:", dish)case dish := <-chef2:fmt.Println("厨师chef2已经做好了:", dish)case <-time.After(time.Second * 3): //对通道进行超市时间处理时候常用time.Afterfmt.Println("你们做饭太慢了,我不吃了,拜拜")}
// select包含多个case语句,每个case语句用于接收某一个通道的数据,当某一个通道有了数据之后,就会执行对应的case语句。多个case语句,同时都包含了数据,不确定,会随机执行某一个
//练习
package mainimport ("fmt""time"
)// 做菜的函数
func cookDish(chef, dishName string, c chan string) {fmt.Printf("厨师:%s正在做:%s\n", chef, dishName)time.Sleep(time.Second * 5)// 做好的菜放进通道内c <- dishName
}func main() {// 定义两个channel去存放不同的数据chef1 := make(chan string)chef2 := make(chan string)go cookDish("chef1", "烤鸭", chef1)go cookDish("chef2", "佛跳墙", chef2)// 等待获取数据// select包含多个case语句,每个case语句用于接收某一个通道的数据// 当某一个通道有了数据之后,就会执行对应的case语句// 多个case语句,同时都包含了数据,不确定,会随机执行某一个select {case dish := <-chef1:fmt.Println("厨师chef1已经做好了:", dish)case dish := <-chef2:fmt.Println("厨师chef2已经做好了:", dish)case <-time.After(time.Second * 3):fmt.Println("你们做饭太慢了,我不吃了,拜拜")}close(chef1)close(chef2)
}

3.5 监听通道的退出信号

//通过定义Bool类型的通道,可以快速监听退出信号或者监听错误信息
package mainimport ("fmt""time"
)//定义拧螺丝的函数
func screw(c chan int) {i := 1for {fmt.Printf("正在拧第%d个螺丝\n", i)c <- ii++time.Sleep(time.Second)}
}func main() {// 定义一个拧螺丝的通道screwChan := make(chan int, 100)// 定义一个关闭通道的通道stop := make(chan bool)go screw(screwChan)go func() {time.Sleep(10 * time.Second)fmt.Println("下班了,走啦,不干了")stop <- true}()for {select {case <-stop:// 说明我们的倒计时已经到了,并且往stop这个通道内发送了true的数据fmt.Println("下班了,不弄了")returncase s := <-screwChan:fmt.Printf("第%d个螺丝已完成\n", s)}}
}

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

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

相关文章

微服务的应用架构

架构描述的是在更高层次将应用拆分为子系统或模块的方法&#xff0c;以及这些子系统之间的交互关系。在一个基于微服务架构构建的应用中&#xff0c;每个服务都需要有自己的架构。 事实上&#xff0c;单体应用在复杂度较低时&#xff0c;它的生产效率是要高于微服务的。只有在…

React18 入门与进阶

React18 入门与进阶 前言一、核心概念与类组件使用1、虚拟DOM与新的渲染写法2、JSX 与 JSX 的使用3、类组件和函数组件4、类组件与类组件通信5、props详解与注意事项6、类组件中事件的使用7、类组件响应式数据实现与原理8、PureComponent 与 shouldComponentUpdate9、immutable…

Java数据结构之《构造哈夫曼树》题目

一、前言&#xff1a; 这是怀化学院的&#xff1a;Java数据结构中的一道难度中等(偏难理解)的一道编程题(此方法为博主自己研究&#xff0c;问题基本解决&#xff0c;若有bug欢迎下方评论提出意见&#xff0c;我会第一时间改进代码&#xff0c;谢谢&#xff01;) 后面其他编程题…

Difference between getc(), getchar(), and gets()

getc(): 从输入中只能读单个字符 getchar()&#xff1a;从标准输入流中输入都单个字符。 两者基本等同&#xff0c;唯一不一样的是getc()是任何输入流&#xff0c;而getchar()是标准输入流。 gets:可以读入含有空格的字符串 // Example for getc() in C #include <stdio.h…

perl脚本批量处理代码中的中文注释乱码的问题

代码中统一使用utf-8编码是最好的&#xff0c;但是有一些多人合作的项目或者一些历史遗留代码&#xff0c;常见一些中文注释乱码的问题。这里以一个开源项目evpp为例子 evpp。以项目中的一个commit id为例&#xff1a; 477033f938fd47dfecde43c82257cd286d9fa38e &#xff0c; …

算法设计与实现--动态规划篇

什么是动态规划算法 动态规划算法是一种求解复杂问题的方法&#xff0c;通过将原问题分解为相对简单的子问题来求解。其基本思想是将待求解的问题分解为若干个子问题&#xff08;阶段&#xff09;&#xff0c;按顺序求解子阶段&#xff0c;前一子问题的解&#xff0c;为后一子…

市面上的AR眼镜:优缺点分析

AR眼镜是近年来备受关注的科技产品之一。它通过将虚拟信息叠加到现实世界中&#xff0c;为用户提供全新的视觉体验。目前&#xff0c;市面上的AR眼镜主要分为两类&#xff1a;消费级AR眼镜和企业级AR眼镜。 消费级AR眼镜 消费级AR眼镜的特点是轻便、时尚、易于佩戴&#xff0…

面部动作在情绪识别中的作用(nature reviews psychology2023)

文章目录 摘要静态情绪识别动态情感识别时空信息独特的时间信息 动态表情识别的机制动态信息为什么重要什么时候动态信息起作用为什么动态信息很重要 多模态表情识别启发 摘要 过去大多数关于情绪识别的研究都使用了摆拍的表情照片&#xff0c;旨在描绘情绪表现的峰值。虽然这…

正则表达式从放弃到入门(2):grep命令详解

正则表达式从放弃到入门&#xff08;2&#xff09;&#xff1a;grep命令详解 总结 本博文转载自 这是一篇”正则表达式”扫盲贴&#xff0c;如果你还不理解什么是正则表达式&#xff0c;看这篇文章就对了。 如果你是一个新手&#xff0c;请从头阅读这篇文章&#xff0c;如果你…

Mysql窗口函数

1 什么是窗口函数 MySQL从8.0开始支持窗口函数&#xff0c;有的也叫分析函数&#xff08;处理相对复杂的报表统计分析场景&#xff09;&#xff0c;这个功能在大多商业数据库和部分开源数据库中早已支持。 窗口函数&#xff1a;窗口、函数&#xff08;应用在窗口内的函数&…

P-Tuning v2论文概述

P-Tuning v2论文概述 P-Tuning v2论文概述前言微调的限制性P-Tuning的缺陷P-Tuning v2 摘要论文十问NLU任务优化点实验数据集预训练模型实验结果消融实验 结论 P-Tuning v2论文概述 前言 微调的限制性 微调&#xff08;fine-tuning&#xff09;是一种在预训练模型基础上进行目…

中国人工智能

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;作为一项前沿技术在各个领域展现出了强大的潜力。本文将探讨中国人工智能的历史、现状&#xff0c;并展望其未来发展。 人工智能的起源与历史 人工智能的概念最早诞生于1956年的美国达特茅斯学院的夏季研讨会…

【数据库】数据库元素的层次,树形结构的下的多粒度加锁,以及幻象的正确处理

数据库元素的层次 ​专栏内容&#xff1a; 手写数据库toadb 本专栏主要介绍如何从零开发&#xff0c;开发的步骤&#xff0c;以及开发过程中的涉及的原理&#xff0c;遇到的问题等&#xff0c;让大家能跟上并且可以一起开发&#xff0c;让每个需要的人成为参与者。 本专栏会定期…

(学习笔记)Xposed模块编写(一)

前提&#xff1a;需要已经安装Xposed Installer 1. 新建一个AS项目 并把MainActvity和activity_main.xml这两个文件删掉&#xff0c;然后在AndriodManifest.xml中去掉这个Activity的声明 2. 在settings.gralde文件中加上阿里云的仓库地址&#xff0c;否则Xposed依赖无法下载 m…

【llm使用】ChatGLM3-6B Transformers部署调用

文章目录 环境准备模型下载代码准备部署 说明&#xff1a;本文转自国内开源组织datawhale的repo&#xff1a; self-llm 环境准备 在autodl平台中租一个3090等24G显存的显卡机器&#xff0c;如下图所示镜像选择PyTorch–>2.0.0–>3.8(ubuntu20.04)–>11.8 接下来打…

windows 系统读取 Linux Ext 分区硬盘

windows 系统读取 Linux Ext 分区硬盘 起因是需要处理一些在硬盘中的数据&#xff0c;硬盘插到我的电脑上后无法读盘&#xff0c;在 Windows 存储管理器中查看显示未分配&#xff0c;需要格式化&#xff0c;但是在 Ubuntu 系统的电脑中可以正常识别&#xff0c;试验了几次后发…

.NET8构建统计Extreme Optimization Numerical Libraries

为 .NET 8 构建统计应用程序 Extreme Optimization Numerical Libraries for .NET V8.1.22 添加了对 .NET 8 的支持&#xff0c;使您可以使用最新版本的 Microsoft 平台。 Extreme Optimization Numerical Libraries for .NET 是通用数学和统计类的集合&#xff0c;为技术和统计…

【Linux】第二十六站:软硬链接

文章目录 一、软链接二、硬链接三、ln命令四、该如何理解硬链接&#xff1f;五、如何理解软链接六、为什么要用软硬链接1.软链接的应用场景2.硬链接的应用场景 一、软链接 如下所示&#xff0c;我们创建一个文件以后&#xff0c;然后执行下面的指令 ln -s file.txt soft-link…

C++模拟实现unordered_map和unordered_set

目录 1.了解哈希表 1.哈希表 1.他的实现原理就是&#xff1a; ​编辑 2.写单个数据的类型&#xff08;这边先模拟map的kv类型&#xff0c;后面会再一起改&#xff0c;这边先一步步的先简单实现他&#xff09; 3.封装整个类&#xff1a; 4.哈希表中存储string 2.哈…

前后端分离部署https

引用&#xff1a;https://blog.csdn.net/weixin_35676679/article/details/127841598 前后端部署&#xff0c;&#xff0c;一般用的是nginx和java&#xff0c;&#xff0c;&#xff0c; 下载SSL证书&#xff1a; java配置https 将证书配置到springboot中 server:port: 544…