Golang 基于共享变量的并发锁

一、互斥锁

先看一个并发情况,同时操作一个全局变量,如果没有锁会怎么样

假设有1000个goroutines并发进行银行余额的扣除,每次都扣除10元,起始的总余额是10000,理论上并发执行完应该是0对不对,但实际却不是

import ("fmt""sync"
)var balance uint = 10000func withdraw(amount uint) {balance = balance - amountfmt.Println("剩余存款:", balance)defer wg.Done()
}func getBalance() uint {return balance
}func main() {for i := 1; i <= 1000; i++ {wg.Add(1)go withdraw(10)}wg.Wait()fmt.Println(getBalance())
}

得到的结果如下:

这时候就需要引入一个锁来保护balance全局变量,在并发goroutines执行的情况下,防止其他goroutines获取到balance变量进行操作(其他goroutines会处于等待锁的状态)

import ("fmt""sync"
)var balance uint = 10000
var mu sync.Mutex
var wg sync.WaitGroupfunc withdraw(amount uint) {//如果其它的goroutine已经获得了这个锁的话,这个操作会被阻塞直到其它goroutine调用了Unlock使该锁变回可用状态。mutex会保护共享变量。mu.Lock()                       ******************* 增加锁 **********************balance = balance - amountfmt.Println("剩余存款:", balance)mu.Unlock()                     ******************* 释放锁 **********************defer wg.Done()
}func getBalance() uint {return balance
}func main() {for i := 1; i <= 1000; i++ {wg.Add(1)go withdraw(10)}wg.Wait()fmt.Println(getBalance())
}

得到的结果如下:

二、读写锁

RWMutex,即读写互斥锁,适用于读操作远远多于写操作的场景,当多个goroutine需要频繁地读取某个共享资源,而写入操作相对较少时,使用RWMutex可以提高并发性能。

func getBalance() uint {rwMu.RLock()               *********  加锁读取 ********defer rwMu.RUnlock()       ********* 返回释放锁 ********return balance
}

原理:RWMutex允许多个goroutine同时获取读锁(RLock),进行并发读操作,而写锁(Lock)则是互斥的,同一时间只允许一个goroutine进行写操作。当一个goroutine获取读锁时,其他goroutine也可以继续获取读锁来读取数据,而不需要等待。只有当有goroutine尝试获取写锁时,读锁才会被阻塞,这样可以有效地提高并发读取的效率。

sync.RWMutex锁的设计就是为了优化读操作频繁的场景。它能够区分读锁(RLock)和写锁(Lock)

读锁(RLock):
当一个goroutine需要读取共享资源时,它会尝试获取读锁。如果当前没有其他goroutine持有写锁,那么它可以成功获取读锁,并且可以并发地读取数据。如果有其他goroutine已经持有读锁,新的读锁请求也会被允许,从而允许多个goroutine同时读取。

写锁(Lock):
当一个goroutine需要写入共享资源时,它会尝试获取写锁。在写锁被获取之前,所有的读锁和写锁请求都会被阻塞。这意味着,一旦有goroutine开始写操作,其他想要读取或写入的goroutine都必须等待,直到写操作完成并且写锁被释放。

锁的释放:
当一个goroutine完成读取或写入操作后,它会释放相应的锁。如果是读操作完成,它会释放读锁,这样其他正在等待的goroutine就可以获取读锁并开始读取。如果是写操作完成,它会释放写锁,这样其他正在等待的读锁或写锁请求就可以继续进行。

RWMutex的这种设计使得在读操作远多于写操作的情况下,可以提高程序的并发性能。因为多个goroutine可以同时读取,而不需要等待写操作完成,这样就减少了锁竞争,提高了整体的吞吐量。然而,需要注意的是,RWMutex并不是在所有情况下都能提高性能。如果写操作非常频繁,或者读写操作几乎同等频繁,使用RWMutex可能会导致性能下降,因为写操作会阻塞所有读锁和写锁的请求。在这种情况下,使用Mutex可能会更加合适。

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

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

相关文章

spring04:注解使用

spring04&#xff1a;注解使用 文章目录 spring04&#xff1a;注解使用前言&#xff1a;一、 Autowired Qualifier和 Resource 和 nullable1. Autowired 2. Resource &#xff1a;使用在类的属性上面&#xff08;和Autowired类似&#xff09;3. nullable 二、 Component 和 Re…

统信UOS桌面操作系统1060上隐藏Windows磁盘

原文链接&#xff1a;统信UOS桌面操作系统1060上隐藏Windows磁盘 Hello&#xff0c;大家好啊&#xff01;继之前我们讨论了如何在统信UOS桌面操作系统1060上安装双系统之后&#xff0c;今天我要给大家介绍的是&#xff0c;在这个基础上如何隐藏Windows磁盘分区。这样做可以让你…

大数据dolphinscheduler 本地容器化安装

Minio 容器安装 docker run -p 9000:9000 -p 9090:9090 --name minio -d -e "MINIO_ACCESS_KEYminioadmin" -e "MINIO_SECRET_KEYminioadmin" -v D:\SF\DOCKER\minio\data:/data -v D:\SF\DOCKER\minio\config:/root/.minio minio/minio server /da…

特别详细的Spring Cloud 系列教程2:微服务网关gateway的启动

继上一篇&#xff1a;特别详细的Spring Cloud 系列教程1&#xff1a;服务注册中心Eureka的启动 在比较多的教程和书籍里&#xff0c;spring cloud的微服务网关用的Zuul。然而&#xff0c;zuul已经不被官方提倡&#xff0c;现在提倡用的是spring cloud gateway。因为gateway的整…

WPS二次开发系列:Gradle版本、AGP插件与Java版本的对应关系

背景 最近有体验SDK的同学反馈接入SDK出现报错&#xff0c;最终定位到原因为接入的宿主app项目的gradle版本过低导致&#xff0c;SDK兼容支持了android11的特性&#xff0c;需要对应的gradle插件为支持android11的版本。 现象 解决方案 将gradle版本升级至支持android11的插件版…

海外代理IP如何助力YouTube广告投放?

一、海外代理的角色与优势 拓展地理访问&#xff1a; 海外代理允许您从其他国家或地区的IP地址进行网络访问。通过使用海外代理&#xff0c;您可以绕过部分限制&#xff0c;实现访问YouTube和其他平台的目的。扩展受众&#xff1a; 利用海外代理&#xff0c;您可以将广告投放面…

【学习】Spring IoCDI

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f4d5;格言&#xff1a;吾愚多不敏&#xff0c;而愿加学欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 Spring 是什么&#xff1f; 什么是 IoC容器&#xff1f; 传统开发模式 loC开发模式 IoC的优势 IoC 的使用 Bean的…

vue3使用jsQR解析二维码

1.了解jsQR jsQR是一个纯javascript脚本实现的二维码识别库&#xff0c;不仅可以在浏览器端使用&#xff0c;而且支持后端node.js环境。jsQR使用较为简单&#xff0c;有着不错的识别率。 2.效果图 3.二维码 4.下载jsqr包 npm i -d jsqr5.代码 <script setup> import …

迁移docker部署的GitLab

目录 1. 背景2. 参考3. 环境4. 过程4.1 查看原docker启动命令4.2 打包挂载目录传至新宿主机并创建对应目录4.3 保存镜像并传至新宿主机下4.4 新宿主机启动GitLab容器 5 故障5.1 容器不断重启5.2 权限拒绝5.3 容器内错误日志 6 重启容器服务正常7 总结 1. 背景 最近接到一个任务…

【Java】JDK1.8 HashMap源码,put源码详细讲解

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 在Java中&#xff0c;HashMap结构是被经常使用的&#xff0c;在面试当中也是经常会被问到的。这篇文章我给大家分享一下我对于HashMap结构源码的理解。 HashMap的存储与一般的数组不同&#xff0c;HashMap的每一个元素存…

libevent源码解析-定时机制,信号处理,流量控制

概述 libevent的event&#xff0c;event_callback&#xff0c;event_base除了可以用来支持套接字的自动和手动分发&#xff0c;也可用来支持定时机制&#xff0c;信号处理&#xff0e;这里&#xff0c;我们补充对定时机制&#xff0c;信号处理的分析&#xff0e; libevent中的…

c# wpf datagrid 简单试验

1.概要 datagrid 一个列表类的控件 2.代码 <Window x:Class"WpfApp2.Window3"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.mic…

MySOL之旅--------MySQL数据库基础( 3 )

本篇碎碎念:要相信啊,胜利就在前方,要是因为一点小事就停滞不前,可能你也不适合获取胜利,成功的路上会伴有泥石,但是走到最后,你会发现身上的泥泞皆是荣耀的勋章! 今日份励志文案: 凡是发生皆有利于我 目录 查询(select) 1.全列查询 2.指定列查询 3.查询字段为表达式 ​编…

嵌入式中常用的巧妙方法 - (汇总)

概述 做项目&#xff0c;掌握以下方法&#xff0c;可提高开发效率&#xff0c;把时间全部放在需求上。 1、快速获取结构体成员大小 #include <stdio.h> // 获取结构体成员大小 #define GET_MEMBER_SIZE(type, member) sizeof(((type*)0)->member)// 获取结构体成…

SNRO 编号范围对象管控,唯一ID

事务代码:SNRO 代码引用: DATA: MAXTID TYPE I,NEWNO TYPE CHAR8. CALL FUNCTION NUMBER_RANGE_ENQUEUE EXPORTING OBJECT ZQC57 EXCEPTIONS FOREIGN_LOCK 1 OBJECT_NOT_FOUND 2 SYSTEM_FAILURE 3 OTHERS …

Flutter学习13 - Widget

1、Flutter中常用 Widget 2、StatelessWidget 和 StateFulWidget Flutter 中的 widget 有很多&#xff0c;但主要分两种&#xff1a; StatelessWidget无状态的 widget如果一个 widget 是最终的或不可变的&#xff0c;那么它就是无状态的StatefulWidget有状态的 widget如果一个…

使用echarts控件,小程序分包处理上传失败

原因&#xff1a;在小程序中想要使用echarts控件&#xff0c;但是上传代码失败&#xff0c;错误码为主包超过2.5M&#xff0c;基于此&#xff0c;我们使用分包处理&#xff0c;并上传版本。 错误&#xff1a; 使用echarts&#xff1a;在小程序中引入echarts相关文件。 解决方式…

Arduino 项目笔记 |TH1621 LCD液晶显示屏驱动(SSOP-24封装)

LCD液晶屏资料 LCD液晶屏资料 重要参数&#xff1a; 工作电压&#xff1a; 3V可视角度&#xff1a;1201/4 &#xff0c;1/3 TH1621 驱动 HT1621 LCD控制驱动芯片介绍 VLCD 和 VCC 电压符合规格书&#xff0c;最好都取3.3V 。电压太高或太低都会出现段码液晶屏乱码的情况&am…

vue 原理【详解】MVVM、响应式、模板编译、虚拟节点 vDom、diff 算法

vue 的设计模式 —— MVVM M —— Model 模型&#xff0c;即数据V —— View 视图&#xff0c;即DOM渲染VM —— ViewModel 视图模型&#xff0c;用于实现Model和View的通信&#xff0c;即数据改变驱动视图渲染&#xff0c;监听视图事件修改数据 初次渲染 将模板编译为 render …

【Mybatis-Plus】Mybatis-Plus增删改查示例

示例一&#xff1a;delete 这个删除&#xff0c;是我们直接可以把这条记录给放进去&#xff0c;那么这条记录里面如果说有的属性为空的话&#xff0c;它是不会去管的&#xff0c;但是有些属性它不为空的话&#xff0c;那么它就会根据属性。作为一个equal的条件去做一个删除的一…