Golang 并发机制-4:用Mutex管理共享资源
并发性是Go的强大功能之一,它允许多个线程(并发线程)同时执行。然而,权力越大,责任越大。当多个例程并发地访问和修改共享资源时,可能会导致数据损坏、竞争条件和不可预测的程序行为。为了解决这些问题,Go提供了一个称为互斥的同步原语(互斥的缩写)。在本文中,我们将探讨Mutex在管理共享资源中的作用,以及在并发编程中使用它的必要性。
互斥锁简介
互斥锁是一种同步原语,提供对共享资源或代码关键段的独占访问。它充当看门人,一次只允许一个Goroutine访问和修改受保护的资源。当一个线程持有互斥锁时,所有其他试图获取互斥锁的线程都必须等待轮到它们。
互斥锁提供了两个基本方法:
- Lock() :该方法获取互斥对象,授予对资源的独占访问权。如果另一个线程已经持有互斥对象,新的线程将阻塞,直到它被释放。
- Unlock():这个方法释放互斥锁,允许其他等待的例程获取互斥锁并访问资源。
互斥锁应用场景
对互斥锁的需求源于这样一个事实,即共享资源在被多个例程并发访问时容易受到数据竞争和不一致的影响。以下是互斥锁必不可少的一些常见场景:
- 数据竞争
当多个协程并发地访问共享数据,并且其中至少有一个修改共享数据时,就会发生数据竞争。这可能导致不可预测的错误行为,因为无法保证执行顺序。互斥锁通过一次只允许一个协程访问共享资源来防止数据竞争。
package mainimport ("fmt""sync"
)var sharedData int
var mu sync.Mutexfunc increment() {mu.Lock()sharedData++mu.Unlock()
}func main() {var wg sync.WaitGroupfor i := 0; i < 100; i++ {wg.Add(1)go func() {defer wg.Done()increment()}()}wg.Wait()fmt.Println("Shared Data:", sharedData)
}
在这个例子中,多个协程并发地增加sharedData
变量,这将导致没有互斥锁的数据竞争。
- 临界区
临界区是访问共享资源的代码的一部分。当多个go例程试图同时访问同一个临界区时,可能会导致不可预测的行为。互斥锁确保一次只有一个程序进入临界区,保证对共享资源的有序访问。
package mainimport ("fmt""sync"
)var (sharedResource intmu sync.Mutex
)func updateSharedResource() {mu.Lock()// Critical section: Access and modify sharedResourcesharedResource++mu.Unlock()
}func main() {var wg sync.WaitGroupfor i := 0; i < 100; i++ {wg.Add(1)go func() {defer wg.Done()updateSharedResource()}()}wg.Wait()fmt.Println("Shared Resource:", sharedResource)
}
在这个例子中,updateSharedResource
函数代表了一个关键区域,其中sharedResource
被访问和修改。如果没有互斥锁,对这个临界区的并发访问可能会导致不正确的结果。
互斥锁方法
互斥锁提供了两种基本操作:锁定和解锁。让我们从理解互斥锁开始:
- 锁定互斥对象:当一个线程想要访问共享资源或临界区时,它会调用互斥对象上的Lock()方法。如果互斥对象当前处于未锁定状态,它将被锁定,从而允许线程程继续执行。如果互斥锁已经被另一个线程锁住了,调用的线程将被阻塞,直到互斥锁可用。
下面是演示互斥锁的代码示例:
package mainimport ("fmt""sync"
)func main() {var mu sync.Mutexmu.Lock() // Lock the Mutex// Critical section: Access and modify shared resourcefmt.Println("Locked the Mutex")mu.Unlock() // Unlock the Mutex
}
- 解锁互斥锁:当一个线程完成了它的临界区并且不再需要独占访问共享资源时,它调用互斥锁上的Unlock()方法。这个动作释放互斥锁,允许其他例程获取它。
下面是互斥锁解锁的执行方式:
package mainimport ("fmt""sync"
)func main() {var mu sync.Mutexmu.Lock() // Lock the Mutex// Critical section: Access and modify shared resourcefmt.Println("Locked the Mutex")mu.Unlock() // Unlock the Mutexfmt.Println("Unlocked the Mutex")
}
在这个例子中,在临界区之后调用mu.Unlock()
来释放互斥锁,使其可供其他例程使用。
避免死锁
虽然互斥锁是确保并发安全性的强大工具,但如果使用不当,它们也会引入死锁。当两个或多个线程被卡住,等待对方释放资源时,就会发生死锁。要避免死锁,请遵循以下最佳实践:
- Always Unlock:确保互斥锁在锁定后处于解锁状态。如果不这样做,可能会导致死锁。
- 使用
defer
:为了保证互斥锁总是被解锁,可以考虑在函数结束时使用defer
语句来解锁它们。 - 避免循环依赖:要小心循环依赖,在循环依赖中,多个例程会等待彼此释放资源。设计代码以避免这种情况。
package mainimport ("fmt""sync"
)func main() {var mu sync.Mutexmu.Lock() // Lock the Mutex// Critical section: Access and modify shared resource// Oops! Forgot to unlock the Mutex// mu.Unlock() // Uncomment this line to avoid deadlockfmt.Println("Locked the Mutex")// ... Some more code// Potential deadlock if mu.Unlock() is not called
}
在这个例子中,如果‘ mu.Unlock() ’行被遗忘或注释掉,则可能会发生死锁,因为互斥对象无限期地处于锁定状态。
互斥锁vs通道
互斥锁并不是Go中管理并发性的唯一工具;通道是另一种基本机制。下面是互斥锁和通道的简要比较:
- 互斥锁用于保护临界区,并确保对共享资源的独占访问。它们适用于需要对数据访问进行细粒度控制的情况。
- 通道用于程序间的通信和同步。它们为交换数据和同步程序提供了更高层次的抽象。
互斥锁和通道之间的选择取决于程序的具体要求。互斥锁对于需要保护共享数据的场景是理想的,而通道则适合于主要关注程序之间的通信和协调的场景。
最后总结
总之,互斥锁是确保Go中安全并发的强大工具。它们有助于保护关键区,防止数据争用,并确保共享资源的完整性。了解何时以及如何使用互斥锁对于编写既高效又可靠的并发Go程序至关重要。
相关文章:
Golang 并发机制-4:用Mutex管理共享资源
并发性是Go的强大功能之一,它允许多个线程(并发线程)同时执行。然而,权力越大,责任越大。当多个例程并发地访问和修改共享资源时,可能会导致数据损坏、竞争条件和不可预测的程序行为。为了解决这些问题&…...
如何用微信小程序写春联
生活没有模板,只需心灯一盏。 如果笑能让你释然,那就开怀一笑;如果哭能让你减压,那就让泪水流下来。如果沉默是金,那就不用解释;如果放下能更好地前行,就别再扛着。 一、引入 Vant UI 1、通过 npm 安装 npm i @vant/weapp -S --production 2、修改 app.json …...
从零开始:用Qt开发一个功能强大的文本编辑器——WPS项目全解析
文章目录 引言项目功能介绍1. **文件操作**2. **文本编辑功能**3. **撤销与重做**4. **剪切、复制与粘贴**5. **文本查找与替换**6. **打印功能**7. **打印预览**8. **设置字体颜色**9. **设置字号**10. **设置字体**11. **左对齐**12. **右对齐**13. **居中对齐**14. **两侧对…...
LLMs之OpenAI o系列:OpenAI o3-mini的简介、安装和使用方法、案例应用之详细攻略
LLMs之OpenAI o系列:OpenAI o3-mini的简介、安装和使用方法、案例应用之详细攻略 目录 相关文章 LLMs之o3:《Deliberative Alignment: Reasoning Enables Safer Language Models》翻译与解读 LLMs之OpenAI o系列:OpenAI o3-mini的简介、安…...
DeepSeek-R1 低成本训练的根本原因是?
在人工智能领域,大语言模型(LLM)正以前所未有的速度发展,驱动着自然语言处理、内容生成、智能客服等众多应用的革新。然而,高性能的背后往往是高昂的训练成本,动辄数百万美元的投入让许多企业和研究机构望而…...
C语言:结构体
一,结构体 C语⾔已经提供了内置类型,如:char、short、int、long、float、double等,但是只有这些内置类型还是不够的,假设我想描述学⽣,描述⼀本书,这时单⼀的内置类型是不⾏的。 描述⼀个学⽣需…...
java练习(5)
ps:题目来自力扣 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这…...
【高等数学】贝塞尔函数
贝塞尔函数(Bessel functions)是数学中一类重要的特殊函数,通常用于解决涉及圆对称或球对称的微分方程。它们在物理学、工程学、天文学等多个领域都有广泛的应用,例如在波动方程、热传导方程、电磁波传播等问题中。 贝塞尔函数的…...
贪吃蛇实现
1.资料来源 https://learn.microsoft.com/zh-cn/windows/console/getstdhandle 2.前言 简介 贪吃蛇是久负盛名的游戏,和俄罗斯方块、扫雷等游戏位列于经典游戏的行列。 《贪食蛇》中玩家控制一条不断移动的蛇,在屏幕上吃掉出现的食物。每吃掉一个食物…...
Windows电脑本地部署运行DeepSeek R1大模型(基于Ollama和Chatbox)
文章目录 一、环境准备二、安装Ollama2.1 访问Ollama官方网站2.2 下载适用于Windows的安装包2.3 安装Ollama安装包2.4 指定Ollama安装目录2.5 指定Ollama的大模型的存储目录 三、选择DeepSeek R1模型四、下载并运行DeepSeek R1模型五、使用Chatbox进行交互5.1 下载Chatbox安装包…...
在C++中,成员变量必须在对象构造完成前初始化,但初始化的方式有多种...
在C中,成员变量必须在对象构造完成前初始化,但初始化的方式可以有多种,具体取决于成员变量的类型和设计需求。以下是C中成员变量初始化的规则和相关机制: 1. 成员变量必须初始化 如果成员变量是基本类型(如 int、doub…...
maven mysql jdk nvm node npm 环境安装
安装JDK 1.8 11 环境 maven环境安装 打开网站 下载 下载zip格式 解压 自己创建一个maven库 以后在idea 使用maven时候重新设置一下 这三个地方分别设置 这时候maven才算设置好 nvm 管理 npm nodejs nvm下载 安装 Releases coreybutler/nvm-windows GitHub 一键安装且若有…...
算法随笔_37: 交替合并字符串
上一篇:算法随笔_36: 复写零-CSDN博客 题目描述如下: 给你两个字符串 word1 和 word2 。请你从 word1 开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。 返回 合并后的字符串 。 示例…...
w188校园商铺管理系统设计与实现
🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...
(2025 年最新)MacOS Redis Desktop Manager中文版下载,附详细图文
MacOS Redis Desktop Manager中文版下载 大家好,今天给大家带来一款非常实用的 Redis 可视化工具——Redis Desktop Manager(简称 RDM)。相信很多开发者都用过 Redis 数据库,但如果你想要更高效、更方便地管理 Redis 数据&#x…...
【Block总结】Shuffle Attention,新型的Shuffle注意力|即插即用
一、论文信息 标题: SA-Net: Shuffle Attention for Deep Convolutional Neural Networks 论文链接: arXiv 代码链接: GitHub 二、创新点 Shuffle Attention(SA)模块的主要创新在于高效结合了通道注意力和空间注意力,同时通过通道重排技…...
解锁豆瓣高清海报(一) 深度爬虫与requests进阶之路
前瞻 PosterBandit 这个脚本能够根据用户指定的日期,爬取你看过的影视最高清的海报,然后使用 PixelWeaver.py 自动拼接成指定大小的长图。 你是否发现直接从豆瓣爬取下来的海报清晰度很低? 使用 .pic .nbg img CSS 选择器,在 我…...
【机器学习与数据挖掘实战】案例11:基于灰色预测和SVR的企业所得税预测分析
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈机器学习与数据挖掘实战 ⌋ ⌋ ⌋ 机器学习是人工智能的一个分支,专注于让计算机系统通过数据学习和改进。它利用统计和计算方法,使模型能够从数据中自动提取特征并做出预测或决策。数据挖掘则是从大型数据集中发现模式、关联…...
聚簇索引、哈希索引、覆盖索引、索引分类、最左前缀原则、判断索引使用情况、索引失效条件、优化查询性能
聚簇索引 聚簇索引像一本按目录排版的书,用空间换时间,适合读多写少的场景。设计数据库时,主键的选择(如自增ID vs 随机UUID)会直接影响聚簇索引的性能。 什么是聚簇索引? 数据即索引:聚簇索引…...
克隆OpenAI(基于openai API和streamlit)
utils.py: from langchain_openai import ChatOpenAI from langchain.memory import ConversationBufferMemory from langchain.chains import ConversationChain import osdef get_chat_response(api_key,prompt,memory): # memory不能是函数的内部局部变量&…...
DeepSeek技术深度解析:从不同技术角度的全面探讨
DeepSeek技术深度解析:从不同技术角度的全面探讨 引言 DeepSeek是一个集成了多种先进技术的平台,旨在通过深度学习和其他前沿技术来解决复杂的问题。本文将从算法、架构、数据处理以及应用等不同技术角度对DeepSeek进行详细分析。 一、算法层面 深度学…...
完全卸载mysql server步骤
1. 在控制面板中卸载mysql 2. 打开注册表,运行regedit, 删除mysql信息 HKEY_LOCAL_MACHINE-> SYSTEM->CurrentContolSet->Services->EventLog->Application->Mysql HKEY_LOCAL_MACHINE-> SYSTEM->CurrentContolSet->Services->Mysql …...
2025年大年初一篇,C#调用GPU并行计算推荐
C#调用GPU库的主要目的是利用GPU的并行计算能力,加速计算密集型任务,提高程序性能,支持大规模数据处理,优化资源利用,满足特定应用场景的需求,并提升用户体验。在需要处理大量并行数据或进行复杂计算的场景…...
机器学习优化算法:从梯度下降到Adam及其实验改进
机器学习优化算法:从梯度下降到Adam及其实验改进 在机器学习和深度学习领域,模型的训练过程本质上是一个优化问题。优化算法的作用是通过调整模型参数,使得模型在给定的数据 集上实现最优性能。而优化算法的效率和效果直接决定了模型的收敛速…...
在 Ubuntu 中使用 Conda 创建和管理虚拟环境
Conda 是一个广泛使用的包管理和环境管理系统,尤其适用于数据科学和 Python 开发。本文将指导你如何在 Ubuntu 系统中安装 Conda 并创建基于 python3.11 的虚拟环境。 1. 安装 Miniconda 或 Anaconda 方法 1:下载并安装 Miniconda Miniconda 是一个轻量…...
【深度学习】搭建卷积神经网络并进行参数解读
第一步 导包 import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F from torchvision import datasets,transforms import matplotlib.pyplot as plt import numpy as np %matplotlib inline transforms 模块是 torchvision 库的…...
稀疏进化训练:机器学习优化算法中的高效解决方案
稀疏进化训练:机器学习优化算法中的高效解决方案 稀疏进化训练:机器学习优化算法中的高效解决方案引言第一部分:背景与动机1.1 传统优化算法的局限性1.2 进化策略的优势1.3 稀疏性的重要性 第二部分:稀疏进化训练的核心思想2.1 稀…...
Vue - Suspense的使用
在 Vue 3 中,Suspense 是一个用于处理异步组件的 API。它允许在加载异步组件时提供一个后备内容(例如加载指示器),从而改善用户体验。在加载期间,可以在页面上显示一个占位符,而不是让用户看到一个空白或错…...
在K8S中,pending状态一般由什么原因导致的?
在Kubernetes中,资源或Pod处于Pending状态可能有多种原因引起。以下是一些常见的原因和详细解释: 资源不足 概述:当集群中的资源不足以满足Pod或服务的需求时,它们可能会被至于Pending状态。这通常涉及到CPU、内存、存储或其他资…...
【算法】回溯算法专题② ——组合型回溯 + 剪枝 python
目录 前置知识进入正题小试牛刀实战演练总结 前置知识 【算法】回溯算法专题① ——子集型回溯 python 进入正题 组合https://leetcode.cn/problems/combinations/submissions/596357179/ 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以…...
理解红黑树
简介:红黑树是一种自平衡二叉查找树,由鲁道夫贝尔(Rudolf Bayer)在1972年发明,最初称为“对称二叉B树”。它的设计旨在解决普通二叉查找树在频繁插入和删除操作时可能退化为链表的问题,从而保持高效的查找、…...
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(OLED设备层封装)
目录 OLED设备层驱动开发 如何抽象一个OLED 完成OLED的功能 初始化OLED 清空屏幕 刷新屏幕与光标设置1 刷新屏幕与光标设置2 刷新屏幕与光标设置3 绘制一个点 反色 区域化操作 区域置位 区域反色 区域更新 区域清空 测试我们的抽象 整理一下,我们应…...
大模型能力评估数据集都有哪些?
大模型能力的评估数据集种类繁多,涵盖了语言理解、推理、生成、代码能力、安全性和鲁棒性等多个方面。以下是一些主要的评估数据集及其特点: 通用能力评估数据集: MMLU:多模态大规模多语言任务理解数据集,覆盖从基础教育到高级专业水平的57个科目,用于评估模型的知识储备…...
论文阅读(二):理解概率图模型的两个要点:关于推理和学习的知识
1.论文链接:Essentials to Understand Probabilistic Graphical Models: A Tutorial about Inference and Learning 摘要: 本章的目的是为没有概率图形模型背景或没有深入背景的科学家提供一个高级教程。对于更熟悉这些模型的读者,本章将作为…...
《OpenCV》——图像透视转换
图像透视转换简介 在 OpenCV 里,图像透视转换属于重要的几何变换,也被叫做投影变换。下面从原理、实现步骤、相关函数和应用场景几个方面为你详细介绍。 原理 实现步骤 选取对应点:要在源图像和目标图像上分别找出至少四个对应的点。这些对…...
【16届蓝桥杯寒假刷题营】第2期DAY4
【16届蓝桥杯寒假刷题营】第2期DAY4 - 蓝桥云课 问题描述 幼儿园小班的浩楠同学有一个序列 a。 他想知道有多少个整数三元组 (i,j,k) 满足 1≤i,j,k≤n 且 aiajak。 输入格式 共2行,第一行一个整数 n,表示序列的长度。 第二行 n 个整数&#x…...
用 HTML、CSS 和 JavaScript 实现抽奖转盘效果
顺序抽奖 前言 这段代码实现了一个简单的抽奖转盘效果。页面上有一个九宫格布局的抽奖区域,周围八个格子分别放置了不同的奖品名称,中间是一个 “开始抽奖” 的按钮。点击按钮后,抽奖区域的格子会快速滚动,颜色不断变化…...
【人工智能学习笔记 一】 AI分层架构、基本概念分类与产品技术架构
新的一年2025要对AI以及LLM有个强化的学习,所以第一篇先对整体有个大概的认知,一直分不清LLM和AI的关系,在整个体系里的位置,以及AIGC是什么东西,AI AGENT类似豆包等和大语言模型的具体关系是什么,整个AI的…...
windows10 配置使用json server作为图片服务器
步骤1:在vs code中安装json server, npm i -g json-server 注意:需要安装对应版本的json server,不然可能会报错,比如: npm i -g json-server 0.16.3 步骤2:出现如下报错: json-server 不是…...
【Elasticsearch 基础入门】Centos7下Elasticsearch 7.x安装与配置(单机)
Elasticsearch系列文章目录 【Elasticsearch 基础入门】一文带你了解Elasticsearch!!!【Elasticsearch 基础入门】Centos7下Elasticsearch 7.x安装与配置(单机) 目录 Elasticsearch系列文章目录前言单机模式1. 安装 J…...
【MySQL】语言连接
语言连接 一、下载二、mysql_get_client_info1、函数2、介绍3、示例 三、其他函数1、mysql_init2、mysql_real_connect3、mysql_query4、mysql_store_result5、mysql_free_result6、mysql_num_fields7、mysql_num_rows8、mysql_fetch_fields9、mysql_fetch_row10、mysql_close …...
【零拷贝】
目录 一:了解IO基础概念 二:数据流动的层次结构 三:零拷贝 1.传统IO文件读写 2.mmap 零拷贝技术 3.sendFile 零拷贝技术 一:了解IO基础概念 理解CPU拷贝和DMA拷贝 我们知道,操作系统对于内存空间&…...
四、GPIO中断实现按键功能
4.1 GPIO简介 输入输出(I/O)是一个非常重要的概念。I/O泛指所有类型的输入输出端口,包括单向的端口如逻辑门电路的输入输出管脚和双向的GPIO端口。而GPIO(General-Purpose Input/Output)则是一个常见的术语,…...
qt-Quick3D笔记之官方例程Runtimeloader Example运行笔记
qt-Quick3D笔记之官方例程Runtimeloader Example运行笔记 文章目录 qt-Quick3D笔记之官方例程Runtimeloader Example运行笔记1.例程运行效果2.例程缩略图3.项目文件列表4.main.qml5.main.cpp6.CMakeLists.txt 1.例程运行效果 运行该项目需要自己准备一个模型文件 2.例程缩略图…...
IM 即时通讯系统-01-概览
前言 有时候希望有一个 IM 工具,比如日常聊天,或者接受报警信息。 其实主要是工作使用,如果是接收报警等场景,其实DD这种比较符合场景。 那么有没有必要再创造一个DD呢? 答案是如果处于个人的私有化使用࿰…...
二叉树——429,515,116
今天继续做关于二叉树层序遍历的相关题目,一共有三道题,思路都借鉴于最基础的二叉树的层序遍历。 LeetCode429.N叉树的层序遍历 这道题不再是二叉树了,变成了N叉树,也就是该树每一个节点的子节点数量不确定,可能为2&a…...
Baklib构建高效协同的基于云的内容中台解决方案
内容概要 随着云计算技术的飞速发展,内容管理的方式也在不断演变。企业面临着如何在数字化转型过程中高效管理和协同处理内容的新挑战。为应对这些挑战,引入基于云的内容中台解决方案显得尤为重要。 Baklib作为创新型解决方案提供商,致力于…...
MP4基础
一、什么是MP4? MP4是一套用于音频、视频信息的压缩编码标准,由国际标准化组织(ISO)和国际电工委员会(IEC)下属的“动态图像专家组”(Moving Picture Experts Group,即MPEGÿ…...
年化18%-39.3%的策略集 | backtrader通过xtquant连接qmt实战
原创内容第785篇,专注量化投资、个人成长与财富自由。 大年初五,年很快就过完了。 其实就是本身也只是休假一周,但是我们赋予了它太多意义。 周五咱们发布发aitrader v4.1,带了backtraderctp期货的实盘接口: aitra…...
通过Redisson构建延时队列并实现注解式消费
目录 一、序言二、延迟队列实现1、Redisson延时消息监听注解和消息体2、Redisson延时消息发布器3、Redisson延时消息监听处理器 三、测试用例四、结语 一、序言 两个月前接了一个4万的私活,做一个线上商城小程序,在交易过程中不可避免的一个问题就是用户…...