go 并发 gorouting chan channel select Mutex sync.One
goroutine
// head: 前缀 index:是一个int的指针
func print(head string, index *int) {for i := 0; i < 5; i++ {// 指针对应的int ++*index++fmt.Println(*index, head, i)// 暂停1stime.Sleep(1 * time.Second)}
}/*
Go 允许使用 go 语句开启一个新的运行期线程,即 goroutine
以一个不同的、新创建的 goroutine 来执行一个函数
同一个程序中的所有 goroutine 共享同一个地址空间。
*/
func main() {fmt.Println("main ...")index := 0go print("first", &index)go print("second", &index)time.Sleep(6 * time.Second)fmt.Println("success ...")
}
chan 一般用法
// 求和,并将数据放在channel中
func sum(arr []int, resultChan chan int) {if len(arr) <= 0 {resultChan <- 0return}var sum = 0for _, value := range arr {sum += value}fmt.Println(sum)// 将结果放在channel中resultChan <- sum
}/*
channel 用于 goroutine之间进行通信1. 创建channelch1 := make(chan 类型) 默认是没有缓冲区的ch2 := make(chan 类型, 缓存长度)2. 添加数据到channel中ch1 <- 1233. 从channel中获取数据var value = <- ch1有无缓冲区区别:
1. 没有缓冲区 按照缓冲区为1来处理,即channel只能放一个数据
2. channel满了后就会阻塞,直到有空位才可以继续放入数据
3. 获取数据类似,阻塞到channel中有数据
*/
func main() {fmt.Println("main ...")// 创建一个没有缓冲区的channelresultChan := make(chan int)array1 := []int{10, 20, 30}array2 := []int{1, 2, 3}// 给两个数组求和并将结果放在channel中go sum(array1, resultChan)go sum(array2, resultChan)// 从channel中获取两个数据,打印到consolefmt.Println(<-resultChan, <-resultChan)fmt.Println("continue ...")// 如果继续获取则会报错:fatal error: all goroutines are asleep - deadlock!// fmt.Println(<-resultChan)fmt.Println("success ...")
}
无缓冲区的chan只能结合goroutine使用
func main() {fmt.Println("main ...")// 创建一个没有缓冲区的channelresultChan := make(chan int)// chan 只能结合goroutine来使用,否则报错// fatal error: all goroutines are asleep - deadlock!resultChan <- 10fmt.Println(<-resultChan)fmt.Println("success ...")
}
有缓冲区的chan可直接赋值
func main() {fmt.Println("main ...")// 创建一个有缓冲区的channelch := make(chan int, 2)ch <- 1ch <- 2fmt.Println(<-ch)fmt.Println(<-ch)fmt.Println("success ...")
}
for rang获取channel数据
func addData(ch chan int, len int) {for i := 0; i < len; i++ {ch <- i}// 如果不关闭,for val := range ch 会阻塞获取数据close(ch)
}/*- 可以使用rang遍历channel,如果channel关闭则直接结束,否则会阻塞等待数据的输入for val := range ch
*/
func main() {fmt.Println("main ...")// 创建一个有缓冲区的channellen := 5ch := make(chan int, len)go addData(ch, len)for val := range ch {fmt.Println(val)}fmt.Println("success ...")
}
select **等待多个goroutine
select可以等待多个goroutine,会阻塞一直到某个case不在阻塞。
func print1(header string, ch1, ch2 chan int) {for i := 0; i < len; i++ {select {case val := <-ch1:fmt.Println(header, val)time.Sleep(time.Second)case ch2 <- i:// do nothing}}
}func main() {fmt.Println("main ...")ch1 := make(chan int)ch2 := make(chan int)go print1("f1", ch1, ch2)go print1("f2", ch2, ch1)time.Sleep(6 * time.Second)fmt.Println("success ...")
}
WaitGroup等待所有goroutine完成
类似java中的CountDownLatch
// 不怎么理解为什么group要用指针
func work(index int, wg *sync.WaitGroup) {defer wg.Done()fmt.Println(index)time.Sleep(time.Second)
}func main() {fmt.Println("main ...")var wg sync.WaitGroupfor i := 0; i < 5; i++ {wg.Add(1)// 为什么要将wg的指针传过去go work(i, &wg)}// 阻塞到所有的goroutine完成后wg.Wait()fmt.Println("success ...")
}
并发锁Mutex
type ConcurrentMap struct {lock sync.Mutexhashmap map[string]int
}// 1. cm *ConcurrentMap 要传指针,否则操作的是副本
// 2. wg *sync.WaitGroup 这个也传指针,确保操作的是一个对象
func (cm *ConcurrentMap) inc(index int, key string, wg *sync.WaitGroup) {defer wg.Done()fmt.Println(index, "start")cm.lock.Lock()before := cm.hashmap[key]fmt.Println(index, "before", before)cm.hashmap[key] = cm.hashmap[key] + 1time.Sleep(time.Microsecond * 100)after := cm.hashmap[key]fmt.Println(index, "after", after)if before+1 != after {fmt.Println(index, "error >>>>>")}cm.lock.Unlock()fmt.Println(index, "end")
}func main() {fmt.Println("main ...")cm := ConcurrentMap{hashmap: make(map[string]int)}var wg sync.WaitGroupfor i := 0; i < 3; i++ {wg.Add(1)go cm.inc(i, "apple", &wg)}wg.Wait()fmt.Println("success ...", cm.hashmap["apple"])
}
RWMutex 读写锁子

参考:
https://www.jianshu.com/p/679041bdaa39
sync.Once 配置文件只加载一次
需求:获取配置文件,如果没有价值只就加载
写法1:
func initMap() {if hasInitMap {return}initMapLock.Lock()defer initMapLock.Unlock()if !hasInitMap {fmt.Println("init map")m = map[string]string{"aaa": "111","bbb": "22",}hasInitMap = true}
}func getValue1(key string) string {initMap()return m[key]
}
写法2:
// 定义一次执行对象
var once sync.Oncefunc initMap2() {m = map[string]string{"aaa": "111","bbb": "22",}
}func getValue2(key string) string {// 一次执行once.Do(initMap2)return m[key]
}func main() {fmt.Println("main ...")for i := 0; i < 20; i++ {fmt.Println(getValue1("aaa"))fmt.Println(getValue2("aaa"))}fmt.Println("success ...")
}
sync.Map 类型ConcurrentHashMap
是安全的Map
atomic.AddInt64(&intV,1) 对基础类型安全操作方法
多线程给变量递增: intV := 3
1. 直接+1 线程不安全
2. 使用Mutex锁代价太大
3. 使用atomic包的方法最好,类似Java中的Atomic

参考
https://blog.csdn.net/weixin_53623989/article/details/136209823
https://blog.csdn.net/e2788666/article/details/130644433
相关文章:
go 并发 gorouting chan channel select Mutex sync.One
goroutine // head: 前缀 index:是一个int的指针 func print(head string, index *int) {for i : 0; i < 5; i {// 指针对应的int *indexfmt.Println(*index, head, i)// 暂停1stime.Sleep(1 * time.Second)} }/* Go 允许使用 go 语句开启一个新的运…...
Unity游戏制作中的C#基础(3)加减乘除算术操作符,比较运算符,逻辑与,或运算符
1. 基本算术运算符 算术运算符主要用于对数值类型(整型和浮点型)进行基本的数学运算。以下是常见的算术运算符及其说明: 运算符描述示例结果加法运算符,用于两个数相加,也可用于字符串连接int a 5 3; string str &…...
深度学习入门--python入门2
以前学的全忘了,现在算是才开始学,有错误,恳请指正。 目录 1.4 Python脚本文件 1.4.1保存为文件 1.4.2 类 1.5 Numpy 1.5.1 导入Numpy 1.5.2 生成Numpy数组 1.5.3 Numpy的算术运算 1.5.4 Numpy的N维数组 1.5.5 广播 1.5.6 访问元素…...
题海拾贝:【枚举】P2010 [NOIP 2016 普及组] 回文日期
Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路! 我的博客:<但凡. 我的专栏:《编程之路》、《数据结构与算法之美》、《题海拾贝》 欢迎点赞,关注! 1、题…...
Mac端homebrew安装配置
拷打了一下午o3-mini-high,不如这位博主的超强帖子,10分钟结束战斗 跟随该文章即可,2025/2/19亲测可行 mac 安装HomeBrew(100%成功)_mac安装homebrew-CSDN博客文章浏览阅读10w次,点赞258次,收藏837次。一直觉得自己写…...
Web - JS基础语法与表达式
概述 这篇文章主要介绍了 JavaScript 的基础语法,包括代码书写位置、ERPL 环境、变量(命名规则、默认值、初始化)、数据类型(基本和复杂,及各类型特点、转换)、表达式和运算符(算数、特殊算数、…...
Python高级语法之selenium
目录: 1、selenium的使用2、selenium元素定位3、selenium使用功能Phantomjs模拟浏览器启动4、selenium使用功能ChromsHandless模拟浏览器启动 1、selenium的使用 2、selenium元素定位 3、selenium使用功能Phantomjs模拟浏览器启动 4、selenium使用功能ChromsHandles…...
AIP-148 标准域
编号148原文链接AIP-148: Standard fields状态批准创建日期2020-10-06更新日期2020-10-06 一些概念在任何API集合中都很常用。对于这些概念,使用统一的标准域名字和行为来表达它们,是非常有用的。 指南 标准域 应当 用于描述其相应概念, 不…...
Docker构建时,设定默认进入的工作目录的方法
在 Docker 中,你可以通过不同的方式来设定容器默认进入的目录,以下针对不同场景分别介绍具体方法: 1. 使用 Dockerfile 设定工作目录 如果你是通过构建镜像的方式来运行容器,那么可以在 Dockerfile 中使用 WORKDIR 指令来设置容器启动时的默认工作目录。以下是具体步骤:…...
2025年3月最新算法-鲸鱼迁徙优化算法Whale Migration Algorithm-附Matlab免费代码
引言 本期介绍了一种基于座头鲸协同迁移行为的创新生物启发式优化方法——鲸鱼迁徙优化算法Whale Migration Algorithm,WMA。该算法于2025年3月最新发表在期刊 Results in Engineering 在本节中,我们概述了开发鲸鱼迁移算法(WMA)…...
day56 第十一章:图论part06
108.冗余连接 注意init初始化 改进: 其实只有一条边冗余,改为,如果两条边在同一个集合里,就输出,不然加入。 #include <iostream> #include <vector> using namespace std;int n 1005; vector<int>…...
flowable适配达梦数据库
文章目录 适配相关问题无法从数据库产品名称“DM DBMS”中推断数据库类型分析解决 构建ibatis SqlSessionFactory时出错:inStream参数为null分析解决 liquibase相关问题问题一:不支持的数据库 Error executing SQL call current_schema: 无法解析的成员访…...
Jenkins整合Jmeter实现接口自动化测试
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 一、安装jmeter 下载:http://jmeter.apache.org/download_jmeter.cgi 这里我用了一台Windows安装jmeter用来写接口测试的脚本,启动前修改j…...
高级推理的多样化推理与验证
25年2月来自波士顿大学、NotBadMath.AI、谷歌、哥伦比亚大学、MIT、Intuit公司和斯坦福大学的论文“Diverse Inference and Verification for Advanced Reasoning”。 OpenAI o1、o3 和 DeepSeek R1 等推理 LLM 在数学和编码方面取得重大进展,但仍发现 IMO 组合问题…...
深入理解 MySQL 8 C++ 源码:SELECT MOD(MONTH(NOW()), 2) 的函数执行过程
MySQL 作为最流行的关系型数据库之一,其内部实现机制一直是开发者探索的热点。本文将以一条简单的 SQL 查询 SELECT MOD(MONTH(NOW()), 2) 为例,深入分析 MySQL 8 源码中内置函数 MOD、MONTH 和 NOW 的执行过程,揭示其底层实现逻辑。 一、SQL…...
清华大学:DeepSeek与AI幻觉(31页PDF)
PDF深入探讨了AI幻觉的概念、原因、评测方法及其实用应用,特别是在金融领域的具体案例。首先介绍了AI幻觉的定义,主要包括数据偏差、泛化困境、知识固化和意图误解四种情况,以及这些因素导致AI产出不合理结果的原因。随后,通过音乐…...
AWS云从业者认证题库 AWS Cloud Practitioner(2.21)
题库持续更新,上方二维码查看完整题库! 公司希望减少开发人员用于运行代码的物理计算资源,通过启用无服务器架构,哪种服务可以满足该需求? A: Amazon Elastic Compute Cloud (Amazon EC2) B: AWS Lambda C:…...
CompletableFuture 使用和源码解读
引言 CompletableFuture 是 Java 8 引入的一个强大的异步编程工具,用于处理异步操作和处理结果。它实现了 Future 和 CompletionStage 接口,提供了丰富的方法来处理异步任务的完成、组合和异常处理。 CompletableFuture本质是对异步线程的返回值…...
C++与Python:两种编程语言的区别
C和Python都是当今编程领域广泛使用的语言,它们各有特色,适用于不同的开发场景。本文将从语言特性、性能、学习难度、应用领域等多个方面探讨C与Python之间的区别。 一、语言特性 类型系统: C:是一种静态类型语言…...
网络工程师 (43)IP数据报
前言 IP数据报是互联网传输控制协议(Internet Protocol,IP)的数据报格式,由首部和数据两部分组成。 一、首部 IP数据报的首部是控制部分,包含了数据报传输和处理所需的各种信息。首部可以分为固定部分和可变部分。 固定…...
京准电钟:水利控制系统网络时间同步设计与应用
京准电钟:水利控制系统网络时间同步设计与应用 京准电钟:水利控制系统网络时间同步设计与应用 引言 在水利工程中,控制系统的高效运行依赖于精准的时间同步。水电站、泵站、闸门控制、水文监测等子系统的协同作业需要毫秒甚至微秒级的时间…...
QML 实现一个动态的启动界面
QML 实现一个动态的启动界面 一、效果查看二、源码分享三、所用到的资源下载 一、效果查看 二、源码分享 工程结构 main.qml import QtQuick import QtQuick.Controls import QtQuick.Dialogs import Qt.labs.platformWindow {id:windowwidth: 640height: 400visible: truetit…...
伪404兼容huawei生效显示404
根据上述思考,以下是详细的中文分步说明: --- **步骤 1:获取目标设备的User-Agent信息** 首先,我们需要收集目标设备的User-Agent字符串,包括: 1. **iPhone设备的User-Agent**: Mozi…...
程序代码篇---Python指明函数参数类型
文章目录 前言简介一、函数参数的类型指定1. 基本类型提示2. 默认参数3. 可变参数4. 联合类型(Union)5. 可选类型(Optional)6. 复杂类型 二、返回值的类型指定1. 基本返回类型2. 无返回值(None)3. 返回多个…...
【论文阅读】SAM-CP:将SAM与组合提示结合起来的多功能分割
导言 近年来,视觉基础模型的快速发展推动了多模态理解的进步,尤其是在图像分割任务中。例如,Segment Anything模型(SAM)在图像Mask分割上表现出色,但在语义及实例分割方面仍存在局限。本文提出的SAM-CP&am…...
ecovadis社会企业责任认证
EcoVadis 是一家全球性的企业社会责任 (CSR) 评级机构,旨在通过评估企业在环境、劳工与人权、商业道德和可持续采购等方面的表现,帮助提升其可持续性和社会责任实践。 EcoVadis 认证的核心内容 环境 评估企业在能源消耗、碳排放、废物管理等方面的表现。…...
机器视觉3D中,深度图与点云图数据对比分析
在机器视觉3D中,深度图(Depth Map)和点云图(Point Cloud)是两种不同的数据表示形式,主要区别如下: 数据维度与结构 深度图 二维矩阵:每个像素存储对应场景中某一点的深度值(即到相机的距离)。 坐标系:基于图像坐标系(2D),每个像素的坐标是 (u, v),对应的深度值为…...
逻辑架构与软件架构在PREEvision中的设计关系
1 Introduction 在如今汽车电子系统的开发过程中,系统架构设计是至关重要的环节。无论是汽车控制系统、信息娱乐系统,还是电动驱动系统,架构设计都决定了整个系统的功能、性能以及后期的可维护性和可扩展性。 在往期文章中,我们…...
机器学习和深度神经网络 参数调参数 太麻烦,非常费时间怎么办,用自动化超参数优化方法
自动化超参数优化方法主要包括以下几种: 网格搜索(Grid Search):网格搜索是通过在给定的超参数搜索空间内尝试所有可能的组合,最后找出最优的超参数组合。这种方法虽然直观,但计算成本较高࿰…...
武汉火影数字|VR沉浸式空间制作 VR大空间打造
VR沉浸式空间制作是指通过虚拟现实技术创建一个逼真的三维环境,让用户能够沉浸在这个环境中,彷佛置身于一个全新的世界。 也许你会好奇,VR 沉浸式空间究竟是如何将我们带入那奇妙的虚拟世界的呢?这背后,离不开一系列关…...
