Golang中的锁机制

news2025/1/11 5:28:51

在Go语言中,处理并发问题时通常优先考虑使用信道(channel),但在某些情况下,当信道无法解决问题时,就需要使用锁机制来处理共享内存的并发访问。Go语言提供了两种主要的锁类型:互斥锁(Mutex)和读写锁(RWMutex)。

1. 互斥锁(Mutex)

互斥锁用于保护资源,防止并发操作引起的冲突和数据不准确。在Go中,可以通过sync.Mutex来实现互斥锁。例如,以下代码展示了如何使用互斥锁来保护一个计数器的并发访问:

package main

import (
"fmt"
"sync"
)

func add(count *int, wg *sync.WaitGroup, lock *sync.Mutex) {
for i := 0; i < 1000; i++ {
lock.Lock()
*count = *count + 1
lock.Unlock()
}
wg.Done()
}

func main() {
var wg sync.WaitGroup
lock := &sync.Mutex{}
count := 0
wg.Add(3)
go add(&count, &wg, lock)
go add(&count, &wg, lock)
go add(&count, &wg, lock)

wg.Wait()
fmt.Println("count 的值为:", count)
}

在使用互斥锁时,需要注意以下几点:

  • 同一协程内,不要在未解锁前再次加锁。

  • 同一协程内,不要对已解锁的锁再次解锁。

  • 加锁后,记得解锁,必要时使用defer语句。

2. 读写锁(RWMutex)

sync.RWMutex 是 Go 标准库提供的一种读写锁机制,它可以用于保护共享资源的线程安全访问

读写锁允许多个读操作并发进行,而写操作会阻塞所有读写操作。这种锁机制可以提高程序的效率,特别是在读操作远多于写操作的场景中。

1. 原理解释:

  • sync.RWMutex 分为两种锁:读锁和写锁。
  • 当一个 goroutine 持有读锁时,其他 goroutine 可以同时获取读锁,但不能获取写锁。
  • 当一个 goroutine 持有写锁时,其他 goroutine 既不能获取读锁也不能获取写锁,直到该写锁被释放。

2. 使用方法:

  • r.RLock()/r.RUnlock(): 获取和释放读锁。
  • r.Lock()/r.Unlock(): 获取和释放写锁。
  • 通常在读取共享资源时使用 RLock()/RUnlock(),在写入共享资源时使用 Lock()/Unlock(),以提高并发性能。

3.示例展示:

type TemplateTSMap[TK comparable, TV any] struct {
M map[TK]TV
lock sync.RWMutex
}

在如上TemplateTSMap结构体中的应用;

  • TemplateTSMap 结构体中,我们使用 sync.RWMutex 来保护 M 字段(即底层的 map)。
  • 当一个 goroutine 需要读取 map 中的数据时,它会获取读锁(RLock())。这样可以允许其他 goroutine 同时读取数据,提高并发性能。
  • 当一个 goroutine 需要写入或删除 map 中的数据时,它会获取写锁(Lock())。这样可以确保在写入过程中不会有其他 goroutine 读取或修改数据,保证数据的一致性。
  • 在读取或写入操作完成后,goroutine 需要相应地释放读锁(RUnlock())或写锁(Unlock())。

以下是一个使用读写锁的示例:

package main

import (
"fmt"
"sync"
"time"
)

func main() {
lock := &sync.RWMutex{}
lock.Lock()

for i := 0; i < 4; i++ {
go func(i int) {
fmt.Printf("第 %d 个协程准备开始... \n", i)
lock.RLock()
fmt.Printf("第 %d 个协程获得读锁, sleep 1s 后,释放锁\n", i)
time.Sleep(time.Second)
lock.RUnlock()
}(i)
}

time.Sleep(time.Second * 2)

fmt.Println("准备释放写锁,读锁不再阻塞")
lock.Unlock()

lock.Lock()
fmt.Println("程序退出...")
lock.Unlock()
}

在使用读写锁时,应当注意以下几点:

  • 当有读锁时,写锁会阻塞。

  • 当有写锁时,读锁也会阻塞。

  • 读锁可以并发,不会相互阻塞。

Go语言中的锁机制是处理并发问题时不可或缺的工具。正确使用锁可以保证数据的一致性和程序的稳定性。在实际编程中,应当根据具体的应用场景选择合适的锁类型,并严格遵守锁的使用规则,以避免死锁和其他并发问题。

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

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

相关文章

Java并发编程面试题:内存模型(6题)

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

标准应用 | 2025年网络安全服务成本度量实施参考

01 网络安全服务成本度量依据相关新变化 为了解决我国网络安全服务产业发展中面临的服务供需两方对于服务成本组成认知偏差较大、网络安全服务成本度量缺乏依据的问题&#xff0c;中国网络安全产业联盟&#xff08;CCIA&#xff09;组织北京赛西科技发展有限责任公司、北京安…

太速科技-FMC141-四路 250Msps 16bits AD FMC子卡

FMC141-四路 250Msps 16bits AD FMC子卡 一、产品概述&#xff1a; 本板卡基于 FMC 标准板卡&#xff0c;实现 4 路 16-bit/250Msps ADC 功能。遵循 VITA 57 标准&#xff0c;板卡可以直接与xilinx公司或者本公司 FPGA 载板连接使用。板卡 ADC 器件采用 ADI 公司 AD9467 芯…

通义灵码在跨领域应用拓展之物联网篇

目录 一.引言 二.通义灵码简介 三.通义灵码在物联网领域的设备端应用 1.传感器数据采集 (1).不同类型传感器的数据读取 (2).数据转换与预处理 2.设备控制指令接收和执行 (1).指令解析与处理 (2).设备动作执行 四.通义灵码在物联网领域的云端平台应用 1.数据存储和管…

使用Kubernetes部署Spring Boot项目

目录 前提条件 新建Spring Boot项目并编写一个接口 新建Maven工程 导入 Spring Boot 相关的依赖 启动项目 编写Controller 测试接口 构建镜像 打jar包 新建Dockerfile文件 Linux目录准备 上传Dockerfile和target目录到Linux 制作镜像 查看镜像 测试镜像 上传镜…

C#基础之 继承类相关构造函数使用

类构造函数 作用是为 类中成员变量进行赋值操作 单个类的时候 一般不会有什么思路问题&#xff0c;主要说明一下 有继承关系类的时候 当存在继承关系的类 如 A&#xff1a;B 首先要注意第一点&#xff1a;顺序 那么在构造函数时 顺序是由 B先构造 然后 A在构造 注意第二点方法…

【leetcode刷题】:双指针篇(有效三角形的个数、和为s的两个数)

文章目录 一、有效三角形的个数题目解析算法原理代码编写 二、和为s的两个数题目解析算法原理代码编写 一、有效三角形的个数 题目解析 有效三角形的个数【点击跳转】 题目意思很好理解&#xff1a;就是在一堆非负整数的数组里&#xff0c;随机选三个数进行搭配&#xff0c;…

【Unity3D】apk加密(global-metadata.dat加密)

涉及&#xff1a;apk、aab、global-metadata.dat、jks密钥文件、APKTool、zipalign 使用7z打开apk文件观察发现有如下3个针对加密的文件。 xxx.apk\assets\bin\Data\Managed\Metadata\global-metadata.dat xxx.apk\lib\armeabi-v7a\libil2cpp.so xxx.apk\lib\arm64-v8a\libil…

机器学习之贝叶斯分类器和混淆矩阵可视化

贝叶斯分类器 目录 贝叶斯分类器1 贝叶斯分类器1.1 概念1.2算法理解1.3 算法导入1.4 函数 2 混淆矩阵可视化2.1 概念2.2 理解2.3 函数导入2.4 函数及参数2.5 绘制函数 3 实际预测3.1 数据及理解3.2 代码测试 1 贝叶斯分类器 1.1 概念 贝叶斯分类器是基于贝叶斯定理构建的分类…

前端报告 2024:全新数据,深度解析未来趋势

温馨提示: 此报告为国际版全球报告,其中所涉及的技术应用、工具偏好、开发者习惯等情况反映的是全球前端开发领域的综合态势。由于国内外技术发展环境、行业生态以及企业需求等存在差异,可能有些内容并不完全契合国内的实际情况,请大家理性阅读,批判性地吸收其中的观点与信…

科普CMOS传感器的工作原理及特点

在当今数字化成像的时代&#xff0c;图像传感器无疑是幕后的关键 “功臣”&#xff0c;它宛如一位神奇的 “光影魔法师”&#xff0c;通过光电效应这一奇妙的物理现象&#xff0c;将光子巧妙地转换成电荷&#xff0c;为图像的诞生奠定基础。而在众多类型的图像传感器中&#xf…

word论文排版常见问题汇总

word论文排版常见问题汇总 常用快捷键&#xff1a; Alt F9 正常模式与域代码模式切换 Ctrl F9 插入域代码 F9 刷新域代码显示&#xff0c;要注意选定后刷新才会有效果 word中在当前列表的基础上修改列表 在使用word时&#xff0c;我们会定义一个列表&#xff0c;并将其链接…

使用PVE快速创建虚拟机集群并搭建docker环境

安装Linux系统 这里以安装龙蜥操作系统AnolisOS8.9为例加以说明。 通过PVE后台上传操作系统ISO镜像。 然后在PVE上【创建虚拟机】&#xff0c;选定上传的龙蜥操作系统镜像进行系统安装。 注意&#xff1a;在安装过程中&#xff0c;要设定语言、时区、超管用户root的密码、普…

某音响制造公司发展战略转型项目成功案例纪实

面对产业结构变化、海外订单缩减、劳动力成本攀升、缺乏自主品牌等原因导致的利润空间急剧下降的挑战&#xff0c;面向海外市场的代工厂如何在严峻的经济形势下克服发展障碍&#xff0c;成功实现转型与发展&#xff1f; 某音响制造公司&#xff0c;面临着订单量减少、成本增高…

redis的学习(三)

6. set集合 集合&#xff1a;把一些有关联的数据放在一起。 1、集合中的元素是无序的&#xff0c;即数据存放顺序不重要&#xff0c;变化一下顺序&#xff0c;集合依旧是之前的集合。 2、集合中的元素是不能重复的&#xff08;唯一性&#xff09;与list类似的是集合中的每一个元…

点赞系统设计(微服务)

点赞业务是一个常见的社交功能&#xff0c;它允许用户对其他用户的内容&#xff08;如帖子、评论、图片等&#xff09;表示喜欢或支持。在设计点赞业务时&#xff0c;需要考虑以下几个方面&#xff1a; 一、业务需求 点赞业务需要满足以下特性&#xff1a; 通用&#xff1a;…

C#进阶-在Ubuntu上部署ASP.NET Core Web API应用

随着云计算和容器化技术的普及&#xff0c;Linux 服务器已成为部署 Web 应用程序的主流平台之一。ASP.NET Core 作为一个跨平台、高性能的框架&#xff0c;非常适合在 Linux 环境中运行。本篇博客将详细介绍如何在 Linux 服务器上部署 ASP.NET Core Web API 应用&#xff0c;包…

设计模式-结构型-桥接模式

1. 什么是桥接模式&#xff1f; 桥接模式&#xff08;Bridge Pattern&#xff09; 是一种结构型设计模式&#xff0c;它旨在将抽象部分与实现部分分离&#xff0c;使它们可以独立变化。通过这种方式&#xff0c;系统可以在抽象和实现两方面进行扩展&#xff0c;而无需相互影响…

python学习笔记—16—数据容器之元组

1. 元组——tuple(元组是一个只读的list) (1) 元组的定义注意&#xff1a;定义单个元素的元组&#xff0c;在元素后面要加上 , (2) 元组也支持嵌套 (3) 下标索引取出元素 (4) 元组的相关操作 1. index——查看元组中某个元素在元组中的位置从左到右第一次出现的位置 t1 (&qu…

基础算法--查找

一、线性枚举 1、线性枚举定义 线性枚举指的就是遍历某个一维数组&#xff08;顺序表&#xff09;的所有元素&#xff0c;找到满足条件的那个元素并且返回&#xff0c;返回值可以是下标&#xff0c;也可以是元素本身。 由于是遍历的&#xff0c;穷举了所有情况&#xff0c;所…