Golang 锁介绍

在并发编程中,锁是一种常用的同步机制,用来保护共享资源的安全访问和修改。Golang 作为一门支持并发的语言,提供了两种主要的锁类型:互斥锁(Mutex)和读写锁(RWMutex)。本文将介绍这两种锁的概念、用法和注意事项。

互斥锁

互斥锁是最简单也最常见的一种锁,它用来实现对共享资源的排他访问,即同一时刻只能有一个 goroutine 获得该锁,其他 goroutine 只能等待,直到该锁被释放。Golang 中的互斥锁由 sync.Mutex 结构体表示,它有两个方法:Lock() 和 Unlock()Lock() 方法用来加锁,Unlock() 方法用来解锁。使用互斥锁的一般模式如下:

var mu sync.Mutex // 创建一个互斥锁
mu.Lock() // 加锁
// do something with shared resource
mu.Unlock() // 解锁

互斥锁的使用需要注意以下几点:

  • 不要重复加锁或解锁,否则会导致运行时错误或死锁。
  • 不要忘记解锁,否则会导致其他 goroutine 阻塞,可以使用 defer 语句来确保解锁。
  • 不要在多个函数之间传递互斥锁,否则会增加复杂度和出错的风险,建议将互斥锁和共享资源封装在同一个结构体中,提供加锁和解锁的方法。

互斥锁适用于读写不确定或者写多读少的场景,例如,对一个计数器的增加操作就需要用互斥锁来保证原子性和一致性。下面是一个使用互斥锁的例子:

package mainimport ("fmt""sync"
)var (count intmu    sync.Mutex
)func main() {for i := 0; i < 10; i++ {go func() {for j := 0; j < 10000; j++ {mu.Lock() // 加锁count++    // 修改共享资源mu.Unlock() // 解锁}}()}// 等待所有 goroutine 结束var wg sync.WaitGroupwg.Add(1)go func() {for {mu.Lock() // 加锁c := count // 读取共享资源mu.Unlock() // 解锁if c >= 100000 {break}}wg.Done()}()wg.Wait()fmt.Println(count) // 输出 100000
}

读写锁

读写锁是一种更复杂的锁,它用来实现对共享资源的读写分离,即允许多个 goroutine 同时读取资源,但只允许一个 goroutine 写入资源,从而提高了并发性能。Golang 中的读写锁由 sync.RWMutex 结构体表示,它有四个方法:RLock()RUnlock()Lock() 和 Unlock()RLock() 和 RUnlock() 用来加解读锁,Lock() 和 Unlock() 用来加解写锁。使用读写锁的一般模式如下:

var rw sync.RWMutex // 创建一个读写锁
rw.RLock() // 加读锁
// do something with shared resource for reading
rw.RUnlock() // 解读锁
rw.Lock() // 加写锁
// do something with shared resource for writing
rw.Unlock() // 解写锁

读写锁的使用需要注意以下几点:

  • 不要同时加读锁和写锁,否则会导致死锁。
  • 不要重复加锁或解锁,否则会导致运行时错误或死锁。
  • 不要忘记解锁,否则会导致其他 goroutine 阻塞,可以使用 defer 语句来确保解锁。
  • 不要在多个函数之间传递读写锁,否则会增加复杂度和出错的风险,建议将读写锁和共享资源封装在同一个结构体中,提供加锁和解锁的方法。

读写锁适用于读多写少的场景,例如,对一个缓存的查询操作就可以用读写锁来提高效率。下面是一个使用读写锁的例子:

package mainimport ("fmt""math/rand""sync""time"
)var (cache = make(map[int]int) // 缓存rw    sync.RWMutex        // 读写锁
)func main() {// 模拟多个 goroutine 同时读写缓存for i := 0; i < 10; i++ {go func() {for {key := rand.Intn(5)rw.RLock() // 加读锁value := cache[key] // 从缓存中读取数据rw.RUnlock() // 解读锁fmt.Printf("goroutine %d read key %d value %d\n", i, key, value)time.Sleep(time.Millisecond * 10)}}()}for i := 0; i < 2; i++ {go func() {for {key := rand.Intn(5)value := rand.Intn(100)rw.Lock() // 加写锁cache[key] = value // 向缓存中写入数据rw.Unlock() // 解写锁fmt.Printf("goroutine %d write key %d value %d\n", i+10, key, value)time.Sleep(time.Millisecond * 100)}}()}// 主 goroutine 等待select {}
}

总结

本文介绍了 Golang 中的两种锁类型:互斥锁和读写锁,以及它们的概念、用法和注意事项。互斥锁用来实现对共享资源的排他访问,适用于读写不确定或者写多读少的场景。读写锁用来实现对共享资源的读写分离,适用于读多写少的场景。在使用锁的时候,要注意避免重复加锁或解锁、忘记解锁、死锁等问题,以及尽量减少锁的粒度和范围,提高并发性能。

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

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

相关文章

uniapp 项目 浏览器chrome使用vue devtool 识别不了 in not detect

问题 uniapp的项目&#xff0c;vue2&#xff0c; chrome 分析 添加了运行时&#xff0c;指定模板h5.html 指定的h5.html重置了运行根目录&#xff0c;导致了vue dev tool在运行时&#xff0c;chrome上识别不了。 解决&#xff1a; 方法1&#xff1a; 只能调试的时候,不加sati…

java常用应用程序编程接口(API)——Arrays概述

前言&#xff1a; 学到Arrays了&#xff0c;整理下心得。打好基础&#xff0c;daydayup! Arrays 用来操作数组的一个工具类 Arrays的常见方法 方法名说明public static String toString(类型[] arr)返回数组的内容public static int[ ] copyOfRange(类型[ ] arr,启示索引&…

【操作系统学习笔记】文件管理1.1

【操作系统学习笔记】文件管理1.1 参考书籍: 王道考研 视频地址: Bilibili I/O 设备的基本概念与分类 I/O 设备就是可以将数据输入到计算机&#xff0c;或者可以接收计算机输出数据的外部设备&#xff0c;属于计算机中的硬件设备。UNIX系统将外部设备抽象为一种特殊的文件&a…

2021 年 6 月青少年软编等考 C 语言一级真题解析

目录 T1. 数的输入和输出思路分析 T2. (a / b) c 的值思路分析 T3. 大写字母的判断思路分析 T4. 特殊求和思路分析 T5. 硬币翻转思路分析 T1. 数的输入和输出 输入一个整数和双精度浮点数&#xff0c;先将浮点数保留 2 2 2 位小数输出&#xff0c;然后输出整数。 时间限制&…

SpringMVC框架①

目录 一、SpringMVC概述 1. 什么是MVC 2. 什么是SpringMVC 3. springMVC特点 二、HellWorld 1. 开发环境 2. 创建maven工程 3. 配置web.xml 4. 创建请求控制器 5. 创建springMVC的配置文件 6. 测试HelloWorld 三、RequestMapping注解 1、RequestMapping功能 2、Re…

Android如何实现复制到剪贴板

文章目录 核心代码关于权限举例 在 Android 开发中&#xff0c;可以使用 ClipboardManager 来复制文本到剪贴板。以下是一个简单的示例代码&#xff0c;演示如何将文本复制到剪贴板&#xff1a; 核心代码 // 获取剪贴板管理器 val clipboardManager getSystemService(Contex…

Linux - 安装 maven(详细教程)

目录 一、下载二、安装三、配置环境变量四、镜像资源配置 一、下载 官网&#xff1a;https://maven.apache.org/download.cgi 打开 maven 的官网下载页面&#xff0c;点击 bin.tar.gz 文件链接 即可下载最新版本的 maven 如果想要下载旧版本的 meven&#xff0c;则点击 Maven…

图形系统开发实战课程:进阶篇(上)——9.空间算法(一)

图形开发学院&#xff5c;GraphAnyWhere 课程名称&#xff1a;图形系统开发实战课程&#xff1a;进阶篇(上)课程章节&#xff1a;“图形样式”原文地址&#xff1a;https://www.graphanywhere.com/graph/advanced/2-9.html 第九章 空间算法&#xff08;一&#xff09; \quad 在…

SpringBoot 自定义映射规则resultMap collection一对多

介绍 collection是封装一对多关系的&#xff0c;通常情况下是一个列表&#xff0c;association是一对一&#xff0c;通常情况是一个对象。例如&#xff1a;查询班级下所有的学生&#xff0c;一个班级可以有多个学生&#xff0c;这就是一对多。 案例 有一个学生表&#xff0c…

基于 Redis 的 JWT令牌失效方案

应用场景 当用户登录状态到登出状态时&#xff0c;对应的JWT的令牌需要设置为失效状态&#xff0c;这时可以使用基于 Redis 的黑名单方案来实现JWT令牌失效。 基于 Redis 的黑名单方案 当用户需要登出系统时&#xff0c;将用户携带的Token进行解析&#xff0c;解码出JWT令牌…

Go语言中的时间控制:定时器技术详细指南

Go语言中的时间控制&#xff1a;定时器技术详细指南 引言定时器基础创建和使用time.Timer使用time.Ticker实现周期性任务定时器的内部机制小结 使用time.Timer实现简单的定时任务创建和启动定时器停止和重置定时器定时器的实际应用小结 利用time.Ticker处理重复的定时任务创建和…

这里推荐一款unity3d人物动物控制器详细的等学会再写文章

unity3d Animal Controller 1.4.0a 动物NPC行为控制器 动物控制器&#xff08;AC&#xff09;是一个基于脚本架构的动画框架控制器。它适用于任何动物或人形角色的根运动或原地动画。 人和动物的各种动作都有; 小白必选、 我只是运行乐demo就感觉牛 demo路径&#xff1a;Asset…

Python不换行print在终端中不显示

问题描述 当使用不换行 print 即 print(‘test, end) 后立即关闭标准输出 sys.stdout open(os.devnull, w)则 print 的内容不会显示在正常的终端上&#xff08;例外是 PyCharm 中的终端能够正常显示&#xff09;。 复现问题 复现该问题的简易代码&#xff1a; import sys,…

基于pytorch的手写体识别

一、环境搭建 链接: python与深度学习——基础环境搭建 二、数据集准备 本次实验用的是MINIST数据集&#xff0c;利用MINIST数据集进行卷积神经网络的学习&#xff0c;就类似于学习单片机的点灯实验&#xff0c;学习一门机器语言输出hello world。MINIST数据集&#xff0c;可以…

【go从入门到精通】go环境安装和第一个经典程序

go下载和环境变量配置 下载地址 Go官网下载地址&#xff1a;https://golang.org/dl/All releases - The Go Programming Languagehttps://golang.org/dl/ 然后根据自己的系统环境来选择不同的安装包下载&#xff0c;下面我分别针对不同环境进行说明&#xff08;大家可以根据自…

计算机网络中常用的命令

Ping 通过发送一系列的ICMP回送数据报来确定本机与目的主机是否可以正常通信。输出中TTL代表ICMP报文存活时间&#xff0c;可以推算报文经过了几个路由器。ping失败有可能是由于Windows防火墙-IPv4回显请求没有开启。Ipconfig 获取主机的网络配置信息&#xff0c;例如IP地址、子…

LeetCode 438. 找到字符串中所有字母异位词

对于判断两个词是否为异位词&#xff0c;可以改而判断它们的词频表是否相同。基于此&#xff0c;在s串中设置滑动窗口&#xff0c;大小跟p串一样&#xff0c;移动&#xff08;剔除左边&#xff0c;增加右边&#xff09;这个窗口并实时记录下它的词频表然后与p的词频表比较。 cl…

数据库之Oracle数据导入导出

目录 一、单表导出和导入1、单表导出数据2、单表导入数据二、全表导出和导入1、远程导出全表数据2、导入本地数据三、密码带特殊字符的写法1、Windows OS写法2、Linux/Unix OS写法 四、总结 一、单表导出和导入 1、单表导出数据 --导出远程服务上的表数据 exp 用户名/密码IP…

Platformview在iOS与Android上的实现方式对比

Android中早期版本Platformview的实现基于Virtual Display。VirtualDisplay方案的原理是&#xff0c;先将Native View绘制到虚显&#xff0c;然后Flutter通过从虚显输出中获取纹理并将其与自己内部的widget树进行合成&#xff0c;最后作为Flutter在 Android 上更大的纹理输出的…

【java】redis的bitmap实现签到功能

功能&#xff1a; 1.签到 2.判断某天是否签到 3.统计某月的签到情况 4.统计某月连续签到了多少天 5.统计某月一共签到了多少次 代码 1.依赖 <dependencies><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId>…