GO学习之 互斥锁、读写锁该如何取舍

GO系列

1、GO学习之Hello World
2、GO学习之入门语法
3、GO学习之切片操作
4、GO学习之 Map 操作
5、GO学习之 结构体 操作
6、GO学习之 通道(Channel)
7、GO学习之 多线程(goroutine)
8、GO学习之 函数(Function)
9、GO学习之 接口(Interface)
10、GO学习之 网络通信(Net/Http)
11、GO学习之 微框架(Gin)
12、GO学习之 数据库(mysql)
13、GO学习之 数据库(Redis)
14、GO学习之 搜索引擎(ElasticSearch)
15、GO学习之 消息队列(Kafka)
16、GO学习之 远程过程调用(RPC)
17、GO学习之 goroutine的调度原理
18、GO学习之 通道(nil Channel妙用)
19、GO学习之 同步操作sync包
20、GO学习之 互斥锁、读写锁该如何取舍

文章目录

  • GO系列
  • 前言
  • 一、互斥锁性能测试
  • 二、读写锁性能测试
  • 三、小结

前言

按照公司目前的任务,go 学习是必经之路了,虽然行业卷,不过技多不压身,依旧努力!!!
sync包提供了两种锁,互斥锁(Mutex)和 读写锁(RWMutex),一般有推荐用 互斥锁,它常被用来对结构体对象的内部状态、缓存等进行保护,使用最为广泛。相比之下,读写锁则使用率就不是那么多了,但既然存在,那就有存在的道理和使用场景。

一、互斥锁性能测试

先通过下面一个示例来看一下互斥锁在 cpu = 2 4 8 16 32 的情况下怎么样。
下面的示例中,首先声明一个全局变量 cs 来作为需要保护的临界区数据,声明一个互斥锁对象 mu,测试函数 BenchmarkReadByMutex 中,利用 testing 测试包来执行完成测试,并发执行。

package mainimport ("sync""testing"
)// 模拟临界区需要保护的数据
var cs = 0// 声明互斥锁
var mu sync.Mutexfunc BenchmarkReadByMutex(b *testing.B) {b.RunParallel(func(p *testing.PB) {for p.Next() {mu.Lock()_ = csmu.Unlock()}})
}

测试结果如下:

PS D:\workspaceGo> go test -bench . .\src\sync\sync_mutex_test.go -cpu 2   
goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkReadByMutex-2          75139947                15.35 ns/op
PASS
ok      command-line-arguments  1.418s
PS D:\workspaceGo> go test -bench . .\src\sync\sync_mutex_test.go -cpu 4
goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkReadByMutex-4          48514642                23.85 ns/op
PASS
ok      command-line-arguments  1.479s
PS D:\workspaceGo> go test -bench . .\src\sync\sync_mutex_test.go -cpu 8
goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkReadByMutex-8          27248883                41.00 ns/op
PASS
ok      command-line-arguments  1.435s
PS D:\workspaceGo> go test -bench . .\src\sync\sync_mutex_test.go -cpu 16
goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkReadByMutex-16         19349876                61.73 ns/op
PASS
ok      command-line-arguments  1.486s
PS D:\workspaceGo> go test -bench . .\src\sync\sync_mutex_test.go -cpu 32
goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkReadByMutex-32         18658485                62.07 ns/op
PASS
ok      command-line-arguments  1.490s
  • BenchmarkReadByMutex 后面的 -2 表示 2个CPU线程同时执行;
  • 总共执行了 74433837 次;
  • 每个操作耗时 14.02 纳秒;

我们依次执行 CPU 为 2 4 8 16 32 的情况,发现对于互斥锁性能明显在下降。

二、读写锁性能测试

package mainimport ("sync""testing"
)// 模拟临界区需要保护的数据
var cs = 0// 声明读写锁
var mu sync.RWMutexfunc BenchmarkReadByRWMutex(b *testing.B) {b.RunParallel(func(p *testing.PB) {for p.Next() {mu.Lock()_ = csmu.Unlock()}})
}func BenchmarkWriteByRWMutex(b *testing.B) {b.RunParallel(func(p *testing.PB) {for p.Next() {mu.Lock()cs++mu.Unlock()}})
}

测试结果如下:

PS D:\workspaceGo> go test -bench . .\src\sync\sync_rwmutex_test.go -cpu 2
goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkReadByRWMutex-2        42862144                26.88 ns/op
BenchmarkWriteByRWMutex-2       40500108                29.53 ns/op
PASS
ok      command-line-arguments  4.481s
PS D:\workspaceGo> go test -bench . .\src\sync\sync_rwmutex_test.go -cpu 4
goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkReadByRWMutex-4        24739767                43.13 ns/op
BenchmarkWriteByRWMutex-4       24720604                47.31 ns/op
PASS
ok      command-line-arguments  2.569s
PS D:\workspaceGo> go test -bench . .\src\sync\sync_rwmutex_test.go -cpu 8
goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkReadByRWMutex-8        20657990                54.24 ns/op
BenchmarkWriteByRWMutex-8       20845746                56.85 ns/op
PASS
ok      command-line-arguments  2.666s
PS D:\workspaceGo> go test -bench . .\src\sync\sync_rwmutex_test.go -cpu 16
goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkReadByRWMutex-16       21274909                57.08 ns/op
BenchmarkWriteByRWMutex-16      19730286                60.09 ns/op
PASS
ok      command-line-arguments  3.739s
PS D:\workspaceGo> go test -bench . .\src\sync\sync_rwmutex_test.go -cpu 32
goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkReadByRWMutex-32       21293548                56.24 ns/op
BenchmarkWriteByRWMutex-32      18733052                60.76 ns/op
PASS
ok      command-line-arguments  3.560s

从测试结果中可以看出,我们依旧执行了 CPU 为 2 4 8 16 32 的情况,发现随着线程数的增加,测试函数 BenchmarkReadByRWMutex 和测试函数 BenchmarkWriteByRWMutex 的性能并没有明细变化太大,从 CPU = 2 到 CPU = 4 的时候比较明显,但是从 CPU = 4 8 16 32 性能则趋于比较平稳。

三、小结

对于互斥锁,CPU 从 2 4 8 16 到 32,随着并发量的增加,性能从 15.35 逐步增大到 62.07 ns/op ,也就是每次操作的时间在增大;
对于读写锁,随着并发量的增加,读锁性能并未随并发量的增大而发生较大的变化,始终保持在 50 左右。
通过对互斥锁(sync.Mutex)和 读写锁(sync.RWMutex)的性能测试结果对比,我们得到如下结论:

  • 在并发量较小的情况下,互斥锁 的性能更好,但是随着并发量的逐步增大,互斥锁由于锁竞争激烈,导致加锁和解锁的性能下降;
  • 读写锁的 读锁 性能并未锁着并发量的增大而有大的变化;
  • 在并发量较大的情况下,读写锁的 加锁 性能比 互斥锁、读写锁的读锁 性能都差,并且随着并发量的增大,写锁 性能有继续下降趋势;
  • 读写锁适合在具有一定并发量且 读多写少 的场合。
  • 在大量并发下,在多个 goroutine 可以同时持有读写锁的 读锁,从而减少锁竞争中等待时间;
  • 在大量并发下,互斥锁即便是 读请求,同一时刻也只能有一个 goroutine 持有锁,其他 goroutine 也只能阻塞在加锁操作上,等待被调度;

现阶段还是对 Go 语言的学习阶段,想必有一些地方考虑的不全面,本文示例全部是亲自手敲代码并且执行通过。
如有问题,还请指教。
评论去告诉我哦!!!一起学习一起进步!!!

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

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

相关文章

Postman使用json提取器和正则表达式实现接口的关联

近期在复习Postman的基础知识,在小破站上跟着百里老师系统复习了一遍,也做了一些笔记,希望可以给大家一点点启发。 一)使用json提取器实现接口关联 实际项目场景,在财务信息页面,需要上传一个营业执照&…

C++进阶-STL set/multiset容器和map容器的简单认识

set/multiset容器的简单认识 set基本概念set与multiset 的区别:set容器的构造和赋值set容器的大小和交换set容器的插入与删除set容器的查找和统计set容器-set和multiset的区别set容器内置类型指定排序规则set容器自定义数据类型指定排序规则 pair对组创建map容器的基…

【3年轻量】腾讯云2核2G4M和2核4G5M服务器配置优惠价格表

腾讯云轻量应用服务器特价是有新用户限制的,所以阿腾云建议大家选择3年期轻量应用服务器,一劳永逸,免去续费困扰。腾讯云轻量应用服务器3年可以选择2核2G4M和2核4G5M带宽,3年轻量2核2G4M服务器540元,2核4G5M轻量应用服…

ES-java

全文搜索,拆分,分词--获得id,获取部分数据装载进去,简化版数据,用一种状态展示出来,点击详情走的是数据库查询查看显示详情 倒排索引(特征),创建文档,使用文…

.net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler

asp.net core IHttpClientFactroy 进行SSL(https)请求时注入ConfigurePrimaryHttpMessageHandler解决https请求错误: static public class CreditScoreServiceExtension{static public void AddCreditScoreQueryServiceHttpClient(this IServiceCollection services…

openEuler 系统使用 Docker Compose 容器化部署 Redis Cluster 集群

openEuler 系统使用 Docker Compose 容器化部署 Redis Cluster 集群 Redis 的多种模式Redis-Alone 单机模式Redis 单机模式的优缺点 Redis 高可用集群模式Redis-Master/Slaver 主从模式Redis-Master/Slaver 哨兵模式哨兵模式监控的原理Redis 节点主客观下线标记Redis 节点主客观…

Vue组件传

跟禹神学vue--总结 1 父组件给子组件传递参数--props传参 (1)父组件中准备好数据 data() {return {todos:[{id:001,title:01,done:true},{id:002,title:02,done:false},{id:003,title:03,done:true}]} } (2)父组件中引入子组件…

django建站过程(4)创建文档显示页面

django建站过程(4)创建文档显示页面 创建文档显示页面项目主文件夹schoolapps中的文件urls.py在APP“baseapps”中创建url.py文件编写视图模板继承bootstrap创建head.html创建doclist.html创建docdetail.html 使用 markdown 编辑器安装模块Model 模型的d…

Azure 机器学习 - 机器学习中的企业安全和治理

目录 限制对资源和操作的访问网络安全性和隔离数据加密数据渗透防护漏洞扫描审核和管理合规性 在本文中,你将了解可用于 Azure 机器学习的安全和治理功能。 如果管理员、DevOps 和 MLOps 想要创建符合公司策略的安全配置,那么这些功能对其十分有用。 通过…

Unity中全局光照GI的总结

文章目录 前言一、在编写Shader时,有一些隐蔽的Bug不会直接报错,我们需要编译一下让它显示出来,方便修改我们选择我们的Shader,点击编译并且展示编译后的Shader后的内容,隐蔽的Bug就会暴露出来了。 二、我们大概回顾一…

acwing算法基础之数学知识--判断质数

目录 1 基础知识2 模板3 工程化 1 基础知识 质数和合数,这两个概念都是针对大于等于2的整数定义的。 质数:大于等于2,并且约数只有1和它本身。比如2、3、5、7等等。 判断质数的方法: 从定义出发,时间复杂度O( n \s…

【Python大数据笔记_day06_Hive】

hive内外表操作 建表语法 create [external] table [if not exists] 表名(字段名 字段类型 , 字段名 字段类型 , ... ) [partitioned by (分区字段名 分区字段类型)] # 分区表固定格式 [clustered by (分桶字段名) into 桶个数 buckets] # 分桶表固定格式 注意: 可以排序[so…

红队系列-IOT安全深入浅出

红队专题 设备安全概述物联网设备层次模型设备通信模型 渗透测试信息收集工具 实战分析漏洞切入点D-link 850L 未授权访问 2017 认证绕过认证绕过 D-link DCS-2530Ltenda 系列 路由器 前台未授权RTSP 服务未授权 访问 弱口令命令注入思科 路由器 固件二进制 漏洞 IoT漏洞-D-Lin…

OpenCV C++ 图像处理实战 ——《多二维码识别》

OpenCV C++ 图像处理实战 ——《多二维码识别》 一、结果演示二、zxing库配置2.1下载编译三、多二维码识别3.1 Method one3.1.1 源码3.2 Method two3.2.1 源码四、源码测试图像下载总结一、结果演示 </

国际阿里云、腾讯云.AWS:新加坡服务器数据中心怎么保护网络安全原创

新加坡服务器数据中心怎么保护网络安全原创 保护新加坡服务器数据中心的网络安全是一个重要的任务&#xff0c;以下是一些常见的保护网络安全的办法和办法&#xff1a; 防火墙设置&#xff1a;装备和办理强壮的防火墙来监控和过滤网络流量&#xff0c;阻止未经授权的拜访和歹意…

12.使用若依异步的功能

引言 在软件开发中&#xff0c;经常会遇到耗时操作&#xff0c;有时候耗时操作会对主逻辑的运行时间有影响&#xff0c;但是耗时的操作又不需要实时反馈&#xff0c;就可以使用异步操作。比如日志的记录&#xff0c;启动程序时&#xff0c;也可以降一下启动时候的耗时操作&…

ES6学习

let和const命名 let基本用法-块级作用域 在es6中可以使用let声明变量&#xff0c;用法类似于var ⚠️ let声明的变量&#xff0c;只在let命令所在的代码块内有效 {let a 10;var b 20; } console.log(a); //a is not defined console.log(b); //20不存在变量提升 var命令…

部署ChatGLM3对话预训练模型

ChatGLM3是智谱AI和清华大学KEG实验室联合发布的新一代对话预训练模型。ChatGLM3-6B是ChatGLM3系列中的开源模型&#xff0c;在保留了前两代模型对话流畅、部署门槛低等众多优秀特性的基础上&#xff0c;ChatGLM3-6B引入了如下特性&#xff1a; 更强大的基础模型&#xff1a;C…

Map集合5种遍历方式

1、 方法 package com.csdn; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; public class MapDemo {public static void main(String[] args) {//1、添加元素&#xff1a;无序&#xff0c;不重复&#xff0c;无索引Map…

JAVA -----Java Management Extensions (JMX) 详解1

一、通过Jconsole本地访问 在j2se6之前&#xff0c;需要在应用启动的时候&#xff0c;加上com.sun.management.jmxremote参数&#xff0c;该参数默认值为true&#xff0c;实例如下&#xff1a; java -Dcom.sun.management.jmxremotetrue ,如果禁用本地访问java -Dcom.sun.mana…