GO中sync 包的 RWMutex 读写互斥锁

news2024/11/14 14:45:16

文章目录

    • 背景
    • RWMutex 简介
    • 代码验证
      • 多个协程请求读锁 `RLock()` 和 `RLock()`
      • 读写交错 `RLock()` 和 `Lock()`
        • 写入的时候读取
        • 读取的时候写入
      • 请求多个写`Lock()` 和 `Lock()`

背景

Mutex 互斥锁是严格锁定读和写,如果我们需要单独对读或者写添加锁需要使用 sync包的RWMutex
针对读多写少的情况:

读写锁的原则是
1、可以随便读,多个协程同时读。
2、写的时候,不能读也不能写。

RWMutex 简介

RWMutex 类型一共有 6 个方法,

RLock/RUnlock:RLock 锁定读操作,如果锁已被写操作持有,RLock 方法会被阻塞,直到锁释放;如果锁已被读操作持有,则无限制,可以读取内容。RUnlock 是读操作对应的释放锁的方法。

Lock/Unlock:Lock 锁定读写操作,不管是读操作持有锁,还是写操作持有锁,Lock 方法都会被阻塞,直到锁释放。Unlock 是对应的释放锁方法。一般用于写操作的场景。

rUnlockSlow:检查读操作是否全部释放锁,如果读锁全部释放,才可以唤醒写操作去请求写锁。

RLocker:RLocker 为读操作返回一个 Locker 接口,它的 Lock 方法会调用 RWMutex 类型的 RLock方法,它的 Unlock 方法会调用 RWMutex 类型的 RUnlock方法。

其中 RLock()RLock() 之间并不互斥,可以共享锁,Lock()Lock() 之间还有 RLock()Lock() 之间是互斥的.

代码验证

多个协程请求读锁 RLock()RLock()


package main

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

// 声明Mutex变量
var mu *sync.RWMutex
var count = 0
func main() {
   mu = new(sync.RWMutex)
   for i:= 0; i< 1000; i++ {
      go readLock(i)
   }
   time.Sleep(2*time.Second)
}

func readLock(i int) {
   mu.RLock()
   count++
   fmt.Println(i," Read Lock is", count)
   mu.RUnlock()
}

在这里插入图片描述

如上代码所示, 我们启动1000个协程,每个协程执行的readLock 中都添加了 RLock(). 执行结果如下:

结果发现,count 数字打印杂乱无章,说明这些协程同时持有锁,多个RLock() 之间并不互斥。

读写交错 RLock()Lock()

写入的时候读取


package main

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

// 声明Mutex变量
var mu *sync.RWMutex
var count = 0
func main() {
   mu = new(sync.RWMutex)
   for i := 0; i< 5; i++ {
      go readLock(1)
   }
   for i := 0; i< 5; i++ {
      go writLock(1)
   }
   time.Sleep(30*time.Second)
}

func writLock(i int){
   mu.Lock()
   fmt.Println(i," Writ Lock start", count)
   count++
   fmt.Println(i," Writ Lock is", count)
   time.Sleep(1 *time.Second)
   fmt.Println(i," Writ Lock done", count)
   mu.Unlock()
}

func readLock(i int) {
   mu.RLock()
   fmt.Println(i," Read Lock is", count)
   // time.Sleep(10 *time.Second)
   fmt.Println(i," Read Lock done")
   mu.RUnlock()
}

Lock() 写入的时候,sleep 期间, 使用 RLock() 读取, 结果如下
在这里插入图片描述
发现在 write 等待的时候 read 并没有获得锁, 说明 Lock() 锁未释放, RLock() 不能获得锁

读取的时候写入


package main

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

// 声明Mutex变量
var mu *sync.RWMutex
var count = 0
func main() {
   mu = new(sync.RWMutex)
   for i := 0; i< 10; i++ {
      go readLock(1)
   }
   for i := 0; i< 10; i++ {
      go writLock(1)
   }
   time.Sleep(15*time.Second)
}

func writLock(i int){
   mu.Lock()
   fmt.Println(i," Writ Lock start", count)
   count++
   fmt.Println(i," Writ Lock is", count)
   // time.Sleep(1 *time.Second)
   fmt.Println(i," Writ Lock done", count)
   mu.Unlock()
}

func readLock(i int) {
   mu.RLock()
   fmt.Println(i," Read Lock is", count)
   time.Sleep(10 *time.Second)
   fmt.Println(i," Read Lock done")
   mu.RUnlock()
}

RLock() sleep 期间, 使用 Lock() 结果如下

在这里插入图片描述
read 期间, writ 并没有获得锁。 证明了 RLock()Lock() 是互斥的。

请求多个写Lock()Lock()


package main

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

// 声明Mutex变量
var mu *sync.RWMutex
var count = 0
func main() {
   mu = new(sync.RWMutex)
   for i:= 0; i< 1000; i++ {
      go writLock(i)
   }
   time.Sleep(2*time.Second)
}

func writLock(i int){
   mu.Lock()
   count++
   fmt.Println(i," Writ Lock is", count)
   mu.Unlock()
}

启动1000个线程, 使用 Lock() 执行 count ++, 结果如下
在这里插入图片描述
发现最红结果是1000,并且是按照顺序进行计算的。 说明多个协程之间的Lock() 是互斥的。

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

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

相关文章

Linux服务器快速安装MySQL数据库

Linux服务器快速安装MySQL数据库 mysql官网下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 推荐使用命令下载安装&#xff0c;比较快 开始安装mysql 1.通过wget下载安装包 wget -i -c http://dev.mysql.com/get/mysql57-community-release-el7-10.no…

运动耳机怎样戴不容易掉,运动不容易掉的运动蓝牙耳机推荐

在运动当中总是避免不了大幅度的晃动、跳跃&#xff0c;但是普通的耳机在运动当中佩戴时&#xff0c;耳机会时常出现掉落或者佩戴不牢固的现象发生&#xff0c;下面就给大家分享几款在运动当中佩戴较为稳固的运动蓝牙耳机吧~1、南卡Runner Pro4骨传导蓝牙运动耳机 &#xffe5;…

卡尔曼滤波学习

原教程地址&#xff1a;KalmanFilter.NET 卡尔曼滤波广泛应用在雷达系统&#xff08;目标跟踪&#xff09;中&#xff0c;但是其实它还可以应用在任何需要估算和预测的领域。 一、一维卡尔曼滤波 通过8个数值例子介绍卡尔曼滤波&#xff0c;涉及平均数、方差、标准差等&#…

解决Spring Data Jpa 实体类自动创建数据库表失败问题

先说一下我遇到的这个问题&#xff0c;首先我是通过maven创建了一个spring boot的工程&#xff0c;引入了Spring data jpa&#xff0c;结果实体类创建好之后&#xff0c;运行工程却没有在数据库中自动创建数据表。 找了半天发现是一个配置的问题! hibernate.ddl-auto节点的配…

【python学习笔记】:条件语句

Python 条件语句 Python条件语句是通过一条或多条语句的执行结果&#xff08;True或者False&#xff09;来决定执行的代码块。 可以通过下图来简单了解条件语句的执行过程: Python程序语言指定任何非0和非空&#xff08;null&#xff09;值为true&#xff0c;0 或者 null为fa…

Vue 中过滤器 filter 使用教程

Vue 过滤器 filter 使用教程文章目录Vue 过滤器 filter 使用教程一、过滤器1.1 过滤器使用的背景1.2 格式化时间的不同实现1.3 过滤器的使用1.4 过滤器总结一、过滤器 1.1 过滤器使用的背景 过滤器提供给我们的一种数据处理方式。过滤器功能不是必须要使用的&#xff0c;因为它…

DSP_TMS320F28377D_ADC学习笔记

前言 DSP各种模块的使用&#xff0c;基本上就是 GPIO复用配置、相关控制寄存器的配置、中断的配置。本文主要记录本人对ADC模块的学习笔记。TMS320F28377D上面有24路ADC专用IO&#xff0c;这意味着不需要进行GPIO复用配置。 只需要考虑相关控制寄存器和中断的配置。看代码请直…

2023年湖北住建厅八大员各岗位题库精准小题库-启程别

2023年湖北住建厅八大员各岗位题库精准小题库-启程别 住建厅八大员&#xff08;施工员、质量员、资料员、材料员、机械员、标准员、劳务员&#xff09; 各岗位题库分2种&#xff1a; 1.住建厅八大员报名之后会有培训任务&#xff0c;完成培训任务学习才能安排考试&#xff0c;…

番外10:使用ADS对射频功率放大器进行非线性测试2(使用带宽20MHz的64QAM信号进行ACLR、EVM、CCDF测试)

番外10&#xff1a;使用ADS对射频功率放大器进行非线性测试2&#xff08;使用带宽20MHz的64QAM信号进行ACLR、EVM、CCDF测试&#xff09; 1、基本理论 功率放大器的非线性性能十分重要&#xff0c;特别是对于当前广泛使用的移动设备。由于其各种复杂的信号调制&#xff0c;功…

大数据系统重点

第一章 大数据计算系统概述 1 大数据计算框架概述 计算框架: 一种抽象&#xff0c;在其中提供相应的通用功能供用户编写代码以实现具体功能&#xff0c;从而形成面向应用的软件。 大数据计算框架&#xff1a;面向大数据的计算框架。 Hadoop Hadoop的运行过程 Hadoop的详细…

Android 9.0系统源码_通知服务(三)应用发送状态栏通知的流程

前言 应用发送一个显示在状态栏上的通知&#xff0c;对于移动设备来说是很常见的一种功能需求&#xff0c;本篇文章我们将会结合Android9.0系统源码具体来分析一下&#xff0c;应用调用notificationManager触发通知栏通知功能的源码流程。 一、应用触发状态栏通知 应用可以通…

专题:一看就会的C++类模板讲解 (1)

目录 一.类模板的作用 二.类模板的定义&#xff1a; 三.类模板的声明格式&#xff1a; 四.类模板对象 五.再举一个例子 一.类模板的作用 面向对象的程序设计编程实践中&#xff0c;我们可能会面临这样的问题&#xff1a;要实现比较两个数的大小。明明比较两个数的方法都一样…

小米mix2s刷win11和android双系统

在给电脑安装系统的过程中&#xff0c;可能会因为各种原因出现windows无法安装的情况&#xff0c;我在给小米mix2s安装win11时发现出现了“计算机意外地重新启动或遇到错误&#xff0c;windows无法安装”的情况&#xff0c;下面就来教一下大家两种解决方法&#xff0c;希望可以…

进行新类检测以及概念漂移适应的半监督分类框架SACCOS论文阅读笔记

介绍 本文主要想解决基于聚类的概念漂移检测方法中常做出的强假设问题&#xff0c;即假设同类比较接近&#xff0c;异类比较远离&#xff0c;并且还假设新类别出现时通常会连续大量出现。 针对这些问题&#xff0c;本文提出了一种基于数据流的半监督自适应分类框架SACCOS&…

程序员看过都说好的资源网站,看看你都用过哪些?

程序员必备的相关资源网站一.图片专区1.表情包&#xff08;1&#xff09;发表情&#xff08;2&#xff09;逗比拯救世界&#xff08;3&#xff09;搞怪图片生成&#xff08;4&#xff09;哇咔工具2.图标库&#xff08;1&#xff09;Font Awesome&#xff08;2&#xff09;iconf…

基于vscode开发vue项目的详细步骤教程 2 第三方图标库FontAwesome

1、Vue下载安装步骤的详细教程(亲测有效) 1_水w的博客-CSDN博客 2、Vue下载安装步骤的详细教程(亲测有效) 2 安装与创建默认项目_水w的博客-CSDN博客 3、基于vscode开发vue项目的详细步骤教程_水w的博客-CSDN博客 目录 六、第三方图标库FontAwesome 1 安装FontAwesome 解决报…

vulnhub靶场NAPPING: 1.0.1教程

靶场搭建靶机下载地址&#xff1a;Napping: 1.0.1 ~ VulnHub直接解压双击ova文件即可使用软件&#xff1a;靶机VirtualBox&#xff0c;攻击机VMware攻击机&#xff1a;kali信息收集arp-scan -l上帝之眼直接来看看网站可以注册账号&#xff0c;那就先试试。注册完后登入哦。要输…

阿里面试之Hr面,这个套路把我坑惨了......

作为技术类的测试工程师面试&#xff0c;往往要经过多次面试才能拿到心仪的offer&#xff0c;这里面有技术一面、二面…&#xff0c;甚至总监面等&#xff0c;还有一个必不可少的就是HR面&#xff0c;一般HR会出现在你面试的最前面和最后面&#xff0c;前面是了解你的基本情况&…

NCRE计算机等级考试Python真题(六)

第六套试题1、算法的时间复杂度是指A.执行算法程序所需要的时间B.算法程序的长度C.算法程序中的指令条数D.算法执行过程中所需要的基本运算次数正确答案&#xff1a; D2、下列关于栈的叙述中正确的是A.在栈中只能插入数据B.在栈中只能删除数据C.栈是先进先出的线性表D.栈是先进…

JavaEE简单示例——MyBatis多对多关联映射

简单介绍&#xff1a; 在实际的开发中&#xff0c;多对多的查询也是非常常见的。比如一个订单可以有很多的商品&#xff0c;而一个商品也可以被很多的订单所包含&#xff0c;而这种时候&#xff0c;如果我们有需求查询某一个订单内包含的所有商品&#xff1b;或者查询购买这个…