Go语言中的`sync`包同步原语

在这里插入图片描述

通过sync包掌握Go语言的并发

并发是现代软件开发的基本方面,而Go(也称为Golang)为并发编程提供了一套强大的工具。在Go中用于管理并发的基本包之一是sync包。在本文中,我们将概述sync包,并深入探讨其最关键的同步原语之一:等待组(Wait Groups)。

sync包概述

sync包是Go的标准库包,为并发编程提供了同步原语。它为开发人员提供了协调和同步Goroutines的工具,确保并发任务的安全和有序执行。sync包提供的一些关键同步原语包括Mutexes、RWMutexes、Cond和Wait Groups。

等待组(Wait Groups)

什么是等待组?

等待组是Go中sync包提供的一个同步原语。它是一个简单但强大的工具,用于管理Goroutines的同步,特别是当您希望在继续之前等待一组Goroutines完成其任务时。

等待组在您有多个Goroutines同时执行独立任务,并且您需要确保所有任务都已完成后再继续主程序的场景中非常有用。

如何使用等待组

让我们通过一个代码示例来探索如何使用等待组:

package mainimport ("fmt""sync""time"
)func worker(id int, wg *sync.WaitGroup) {defer wg.Done() // Decrement the Wait Group counter when donefmt.Printf("Worker %d is working\n", id)time.Sleep(time.Second)fmt.Printf("Worker %d has finished\n", id)
}func main() {var wg sync.WaitGroupfor i := 1; i <= 3; i++ {wg.Add(1) // Increment the Wait Group counter for each Goroutinego worker(i, &wg)}wg.Wait() // Wait for all Goroutines to finishfmt.Println("All workers have finished.")
}

在这个示例中,我们定义了一个名为worker的函数,该函数通过休眠一秒来模拟工作。我们启动了三个Goroutines,每个代表一个工作者,并使用sync.WaitGroup来协调它们的执行。

  • wg.Add(1) 在启动每个Goroutine之前增加等待组计数器。
  • wg.Done()worker函数中被延迟执行,以在Goroutine完成其工作时减少计数器。
  • wg.Wait() 阻塞主程序,直到所有Goroutines都完成,确保我们等待所有工作者的完成。

RWMutex(读写互斥锁)

RWMutex(读写互斥锁)是Go语言中的一个同步原语,它允许多个Goroutines同时读取共享数据,同时确保写入时的独占访问。在数据频繁读取但较少修改的场景中,它非常有用。

如何使用RWMutex

以下是一个简单的示例,演示如何使用RWMutex:

package mainimport ("fmt""sync""time"
)var (data        intdataMutex   sync.RWMutex
)func readData() int {dataMutex.RLock() // Read Lockdefer dataMutex.RUnlock()return data
}func writeData(value int) {dataMutex.Lock() // Write Lockdefer dataMutex.Unlock()data = value
}func main() {// Read data concurrentlyfor i := 1; i <= 5; i++ {go func() {fmt.Println("Read Data:", readData())}()}// Write datawriteData(42)time.Sleep(time.Second)
}

在这个示例中,多个Goroutines同时读取共享的data,而一个单独的Goroutine则对其进行写入。RWMutex确保多个读取者可以同时访问数据,但只有一个写入者可以在任何时候修改它。

Cond(条件变量)

什么是条件变量?

条件变量是一种同步原语,允许Goroutines在继续执行之前等待特定条件变为真。当您需要基于某些条件协调多个Goroutines的执行时,它们非常有用。

如何使用Cond

以下是一个基本示例,说明了如何使用条件变量:

package mainimport ("fmt""sync""time"
)var (conditionMutex sync.Mutexcondition      *sync.CondisReady        bool
)func waitForCondition() {conditionMutex.Lock()defer conditionMutex.Unlock()for !isReady {fmt.Println("Waiting for the condition...")condition.Wait()}fmt.Println("Condition met, proceeding.")
}func setCondition() {time.Sleep(2 * time.Second)conditionMutex.Lock()isReady = truecondition.Signal() // Signal one waiting GoroutineconditionMutex.Unlock()
}func main() {condition = sync.NewCond(&conditionMutex)go waitForCondition()go setCondition()time.Sleep(5 * time.Second)
}

在这个示例中,一个Goroutine使用condition.Wait()等待条件变为真,而另一个Goroutine将条件设置为true并使用condition.Signal()通知等待的Goroutine。

原子操作

什么是原子操作?

原子操作是作为单个、不可分割的工作单元执行的操作。它们通常用于在并发程序中安全地更新共享变量,而无需使用互斥锁。Go提供了一个名为atomic的包来进行原子操作。

如何使用原子操作

以下是一个演示原子操作的示例:

package mainimport ("fmt""sync""sync/atomic""time"
)var (counter int32wg      sync.WaitGroup
)func incrementCounter() {defer wg.Done()for i := 0; i < 100000; i++ {atomic.AddInt32(&counter, 1)}
}func main() {wg.Add(2)go incrementCounter()go incrementCounter()wg.Wait()fmt.Println("Counter:", atomic.LoadInt32(&counter))
}

在这个示例中,两个Goroutines使用原子操作递增一个共享的counter变量。atomic.AddInt32函数确保递增操作是原子的,并且对并发访问是安全的。

选择正确的同步机制

在选择适当的同步机制时,请考虑以下准则:

  1. 互斥锁(对于读取使用RWMutex,对于写入使用Mutex) 在你需要对访问进行细粒度控制时,非常适合保护共享数据。
  2. 条件变量 在你需要基于特定条件协调Goroutines时非常有价值。
  3. 原子操作 在你想避免互斥锁开销的情况下,对共享变量进行简单操作非常高效。
  4. 始终选择最能满足特定用例要求的同步机制。

总之,Go语言在sync包中提供了一套多才多艺的同步机制,以及用于管理对共享资源的并发访问的原子操作。了解这些工具并为您的并发需求选择合适的工具是编写高效可靠的并发Go程序的关键。

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

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

相关文章

Modbus RTU转Modbus TCP模块,RS232/485转以太网模块,YL102 多功能串口服务器模块

特点&#xff1a; ● Modbus RTU协议自动转换成Mobus TCP协议 ● 100M高速网卡&#xff0c;10/100M 自适应以太网接口 ● 支持 AUTO MDI/MDIX&#xff0c;可使用交叉网线或平行网线连接 ● RS232波特率从300到256000可设置 ● 工作方式可选择TCP Server, TCP Client, U…

WPF项目创建HTTP WEB服务,不使用IIS业务 WPF桌面程序WebApi WPF 集成WebApi C# 创建HTTP Web API服务

在C# WPF应用程序中直接创建HTTP服务或WebAPI服务有以下优点&#xff1a; 自托管服务&#xff1a; 简化部署&#xff1a;无需依赖外部服务器或IIS&#xff08;Internet Information Services&#xff09;&#xff0c;可以直接在应用程序内部启动和运行Web服务。 集成紧密&…

axios配置请求头content-type 和 get/post请求方式

axios配置请求头content-type https://blog.csdn.net/wojiushiwo945you/article/details/107653962 axios 是Ajax的一个插件&#xff0c;axios虽然是一个插件&#xff0c;但是我们不需要通过Vue.use(axios)来使用&#xff0c;下载完成后&#xff0c;只需在项目中引入即可。(一…

HBase 例行灾备方案:快照备份与还原演练

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

人工智能 机器学习 深度学习:概念,关系,及区别说明

如果过去几年&#xff0c;您读过科技主题的文章&#xff0c;您可能会遇到一些新词汇&#xff0c;如人工智能&#xff08;Artificial Intelligence&#xff09;、机器学习&#xff08;Machine Learning&#xff09;和深度学习&#xff08;Deep Learning&#xff09;等。这三个词…

【Unity学习笔记】1.创建场景

创建场景 注1&#xff1a;samplescene&#xff08;示例场景&#xff09;、standard assets&#xff08;标准资产&#xff09;、favorites&#xff08;收藏夹&#xff09;、terrain&#xff08;地形&#xff09;。 注2&#xff1a;favorites用于存放各种资源&#xff1b;sample…

【C语言】数组

㊙️小明博客主页&#xff1a;➡️ 敲键盘的小明 ㊙️ ✅关注小明了解更多知识☝️ 文章目录 前言一、什么是数组&#xff1f;二、一维数组的创建和初始化2.1 一维数组的创建2.2 一维数组的初始化2.3 一维数组的使用3.3 一维数组的存储 三、二维数组的创建和初始化3.1 二维数组…

每日一题(LeetCode)----二叉树-- 二叉树的右视图

每日一题(LeetCode)----二叉树-- 二叉树的右视图 1.题目&#xff08;199. 二叉树的右视图&#xff09; 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,nu…

Pandas有了平替Polars

Polars是一个Python数据处理库&#xff0c;旨在提供高性能、易用且功能丰富的数据操作和分析工具。它的设计灵感来自于Pandas&#xff0c;但在性能上更加出色。 Polars具有以下主要特点&#xff1a; 强大的数据操作功能&#xff1a;Polars提供了类似于Pandas的数据操作接口&am…

CentOS 5/6/7 基于开源项目制作openssh 9.6p1 rpm包—— 筑梦之路

背景介绍 开源项目地址&#xff1a;https://github.com/boypt/openssh-rpms.git 该项目主要支持了centos 5 、6、7版本&#xff0c;针对使用了比较老的操作系统进行openssh安全加固&#xff0c;还是不错的项目&#xff0c;使用简单、一件制作&#xff0c;欢迎大家去支持作者。…

Linux操作系统极速入门[常用指令](安装jdk,MySQL,nginx),以及在linux对项目进行部署。

linux概述&#xff1a; Linux是一套免费使用和自由传播的操作系统 我们为什么要学&#xff0c;Linux&#xff1f; 主流操作系统&#xff1a; linux系统版本&#xff1a; 内核版&#xff1a; 由linux核心团队开发&#xff0c;维护 免费&#xff0c;开源 负责控制硬件 发行版&…

电路设计(8)——计时器的multism仿真

1.功能设计 这是一个计时电路&#xff0c;在秒脉冲的驱动下&#xff0c;计时器开始累加&#xff0c;6个数码管分别显示计时的 时&#xff1a;分&#xff1a;秒。 仿真图如下所示&#xff1a; 左边的运放构成了振荡电路&#xff0c;可以产生脉冲波。这个脉冲波给计时电路提供基准…

postman进阶使用

前言 对于postman的基础其实很容易上手实现&#xff0c;也有很多教程。 对于小编我来说&#xff0c;也基本可以实现开发任务。 但是今年我们的高级测试&#xff0c;搞了一下postman&#xff0c;省去很多工作&#xff0c;让我感觉很有必要学一下 这篇文章是在 高级测试工程师ht…

数据探查系列:如何进行有意义的探索性数据分析(EDA)

如何进行有意义的探索性数据分析&#xff08;EDA&#xff09; 目录 1. 设置 1.1 导入库1.2 导入数据1.3 数据集特征1.4 数据集属性 2. 探索训练集和测试集 2.1 训练集 - 快速概览2.2 训练集 - 基本统计2.3 测试集 - 快速概览2.4 测试集 - 基本统计 3. 特征分布4. 数据不平衡检查…

websocket 介绍

目录 1&#xff0c;前端如何实现即时通讯短轮询长轮询 2&#xff0c;websocket2.1&#xff0c;握手2.2&#xff0c;握手过程举例2.3&#xff0c;socket.io 3&#xff0c;websocket 对比 http 的优势 1&#xff0c;前端如何实现即时通讯 在 websocket 协议出现之前&#xff0c;…

无需手动搜索!轻松创建IntelliJ IDEA快捷方式的Linux教程

轻松创建IntelliJ IDEA快捷方式的Linux教程 一、IntelliJ IDEA简介二、在Linux系统中创建快捷方式的好处三、命令行创建IntelliJ IDEA快捷方式四、图形界面创建IntelliJ IDEA快捷方式五、常见问题总结 一、IntelliJ IDEA简介 IntelliJ IDEA是一个由JetBrains搞的IDE&#xff0…

vue3+luckyexcel+php在线编辑excel文件

开发过程中&#xff0c;需要开发一个在线编辑excel文档的功能&#xff0c;找到了这个合适的组件 Luckysheet &#xff0c;一款纯前端类似excel的在线表格&#xff0c;功能强大、配置简单、完全开源。 可以导入文档&#xff0c;预览、编辑、保存、导出等功能&#xff0c;可以满…

侦探IP“去推理化”:《名侦探柯南》剧场版走过26年

2023年贺岁档&#xff0c;柯南剧场版的第26部《黑铁的鱼影》如期上映。 这部在日本狂卷票房128亿日元的作品&#xff0c;被誉为有史以来柯南剧场版在商业成绩上最好的一部。 但该作在4月份日本还未上映前&#xff0c;就于国内陷入了巨大的争议。 试映内容里&#xff0c;灰原…

Android原生实现分段选择

六年前写的一个控件&#xff0c;一直没有时间总结&#xff0c;趁年底不怎么忙&#xff0c;整理一下之前写过的组件。供大家一起参考学习。废话不多说&#xff0c;先上图。 一、效果图 实现思路使用的是radioGroup加radiobutton组合方式。原理就是通过修改RadioButton 的backgr…

云计算:OpenStack 配置二层物理网卡为三层桥的接口

目录 一、理论 1.OpenStack 二、实验 1. Linux系统修改网卡 2.OpenStack 配置二层物理网卡为三层桥的接口 一、理论 1.OpenStack &#xff08;1&#xff09;概念 OpenStack是一个开源的云计算管理平台项目&#xff0c;是一系列软件开源项目的组合。由NASA(美国国家航空…