当前位置: 首页 > news >正文

GO中sync 包的 RWMutex 读写互斥锁

文章目录

    • 背景
    • 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 mainimport ("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 mainimport ("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 mainimport ("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 mainimport ("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() 是互斥的。

相关文章:

GO中sync 包的 RWMutex 读写互斥锁

文章目录背景RWMutex 简介代码验证多个协程请求读锁 RLock() 和 RLock()读写交错 RLock() 和 Lock()写入的时候读取读取的时候写入请求多个写Lock() 和 Lock()背景 Mutex 互斥锁是严格锁定读和写&#xff0c;如果我们需要单独对读或者写添加锁需要使用 sync包的RWMutex 针对读…...

糖化学试剂55520-67-7,5-vinyl-2-deoxyuridine,5-乙烯基-2-脱氧尿苷特点分析说明

5-vinyl-2-deoxyuridine(5-VdU)&#xff0c;5-vinyl-2-deoxyuridine&#xff0c;5-Vinyldeoxyuridine5-乙烯基-2-脱氧尿苷 | CAS&#xff1a;55520-67-7 | 纯度&#xff1a;95%试剂信息&#xff1a;CAS&#xff1a;55520-67-7所属类别&#xff1a;糖化学分子量&#xff1a;C11H…...

五年携手共话,FISCO BCOS为数实相生注入新动能

2月24日&#xff0c;作为深圳国际金融科技节系列活动之一&#xff0c;由深圳市地方金融监督管理局指导&#xff0c;微众银行、金链盟主办的“2022产业区块链年度峰会暨FISCO BCOS五周年生态大会”&#xff08;下称“大会”&#xff09;在深圳顺利召开。本次大会以“数实相生&am…...

特征可视化技术t-SNE

特征可视化技术t-SNE 一、理论介绍 想要了解t-SNE的数学原理可以参考t-SNE完整笔记 关于t-SNE的使用过程中有以下几点需要注意&#xff1a; t-SNE算法并不是每次都能产生相似结果。 t-SNE算法使得距离的概念适应于数据集中的区域密度变化。因此&#xff0c;它自然而然地扩大…...

.NET 导入导出Project(mpp)以及发布后遇到的Com组件问题

最近公司项目有一个对Project导入导出的操作&#xff0c;现在市面上能同时对Project进行导入导出的除了微软自带的Microsoft.Office.Interop.MSProject&#xff0c;还有就是Aspose.Tasks for .NET。但因为后者是收费软件且破解版的现阶段只到18.11&#xff0c;只支持.net Frame…...

centos 8安装配置 yum/dnf镜像源 以及 docker相关操作

Docker简介 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 Docker组成部分&#xff1a; 镜…...

java基础之线程池

线程池1.线程池1.1 线程状态介绍1.2 线程池-基本原理1.3 线程池-Executors默认线程池1.4 线程池-Executors创建指定上限的线程池1.5 线程池-ThreadPoolExecutor1.6 线程池-参数详解1.7 线程池-非默认任务拒绝策略2. 原子性2.1 volatile-问题2.2 volatile解决2.3 synchronized解…...

Substrate 基础 -- 教程(Tutorials)

官网 github DOC 面向未来的区块链框架 Substrate 使开发人员能够快速、轻松地构建适合任何用例的未来 证明区块链(future proof blockchains)。 Substrate 文档包括区块链构建器&#xff08;blockchain builders&#xff09;和parachain 项目团队的概念、过程和参考信息。…...

一个线程两次调用start()方法会出现什么情况?

第17讲 | 一个线程两次调用start()方法会出现什么情况&#xff1f; 今天我们来深入聊聊线程&#xff0c;相信大家对于线程这个概念都不陌生&#xff0c;它是 Java 并发的基础元素&#xff0c;理解、操纵、诊断线程是 Java 工程师的必修课&#xff0c;但是你真的掌握线程了吗&am…...

看完再拿五分,软考高项时政提分必备

时事政治题作为软考信息系统项目管理师当中的必考题&#xff0c;每年都让不少考生头疼&#xff0c;主要吧&#xff0c;它一不在教材里&#xff0c;二考的又很随意&#xff0c;如果不是平时积累&#xff0c;专门注意去看&#xff0c;有时候很难答得对&#xff0c;弄得这几分就完…...

界面开发(1) --- PyQt5环境配置

PyQt5环境配置 第一步&#xff1a;首先安装社区版Pycharm 下载地址&#xff1a;https://www.jetbrains.com/pycharm/download/#sectionwindows 第二步&#xff1a;安装Anaconda3&#xff0c;配置虚拟环境 下载地址&#xff1a;https://www.anaconda.com/ 第三步&#xff1…...

shield分析

本文仅供学习交流&#xff0c;只提供关键思路不会给出完整代码&#xff0c;严禁用于非法用途&#xff0c;若有侵权请联系我删除&#xff01;技术交流合作请私信&#xff01; 熟练打开Fiddler设置好手机代理&#xff0c;摆弄半天一直抓不到包&#xff0c;应该是小红书监测到了F…...

Javaweb增删改查之【查】

Javaweb增删改查之【查】1.前端页面2.java链接数据库——集成mybatis2.1 建立层2.2 实体层entity2.3 mapper&#xff08;dao层&#xff09;2.4 mybatis配置文件2.5工具层util3.后台功能3.1servlet前几天跟着b站up主学javaweb登录&#xff0c;突然还是觉得这几年学了c是真的挺好…...

C++ STL:迭代器 Iterator

文章目录1、迭代器的类型2、traitsiterator_traitstype_traits泛化的指针&#xff0c;容器与算法的桥梁。提供一种方法&#xff0c;按照一定顺序访问一个聚合对象中各个元素&#xff0c;而又不暴露该对象的内部表示。既能对容器进行遍历&#xff0c;又可以对外隐藏容器的底层实…...

【C++】泛型编程——模板初阶

文章目录1. 泛型编程2. 函数模板2.1 函数模板的概念2.2 函数模板的使用2.3 函数模板的原理2.4 函数模板的实例化隐式实例化显式实例化2.5 模板参数的匹配原则3. 类模板1. 泛型编程 首先我们来思考一个问题&#xff1a;如何实现一个通用的交换函数呢&#xff1f; 即我们想交换两…...

数据结构入门--时间 空间复杂度

数据结构入门 时间 空间复杂度解析 目录 一. 算法效率 二. 时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 2.3 题目练习 题目一 题目二 题目三 题目四 题目五 题目六 题目七 三. 空间复杂度 3.1 题目练习 题目一 题目二 题目三 一. 算法效率 算法效率…...

计算机操作系统第一章

操作系统引论1.1操作系统的目标和作用定义&#xff1a;操作系统是控制管理计算机系统的硬软件&#xff0c;分配调度资源的系统软件。目标&#xff1a;方便性&#xff0c;有效性&#xff08;提高系统资源的利用率、提高系统的吞吐量&#xff09;&#xff0c;可扩充性&#xff0c…...

ARM LDREX/STREX指令以及独占监控器详解

一、目的Linux驱动开发中有一个特别重要的知识点必须掌握&#xff0c;即并发、竞态以及同步。什么是并发&#xff1f;多个执行单元&#xff08;进程、线程、中断&#xff09;同时对一个共享资源的进行访问&#xff1b;此处的共享资源可以是外设、内存或者软件层面的全局变量静态…...

吉林大学 程序设计基础 2022级 实验复盘 2.23

本人能力有限&#xff0c;发出只为帮助有需要的人。 以下为实验课的复盘&#xff0c;内容会有大量失真&#xff0c;请多多包涵。 此次实验限时一个小时&#xff0c;时间很紧张&#xff0c;很多内容可能并不准确。 1.输出有规律的字母串 输入输出如下&#xff1b; 输入&…...

Linux系列 常用命令(目录和文件管理)vi和vim 编辑使用,(笔记)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.常用命令&#xff08;目录和文件管理&#xff09; 1.查看文件内容 2.统计…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

学习一下用鸿蒙​​DevEco Studio HarmonyOS5实现百度地图

在鸿蒙&#xff08;HarmonyOS5&#xff09;中集成百度地图&#xff0c;可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API&#xff0c;可以构建跨设备的定位、导航和地图展示功能。 ​​1. 鸿蒙环境准备​​ ​​开发工具​​&#xff1a;下载安装 ​​De…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

【WebSocket】SpringBoot项目中使用WebSocket

1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖&#xff0c;添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...

Java后端检查空条件查询

通过抛出运行异常&#xff1a;throw new RuntimeException("请输入查询条件&#xff01;");BranchWarehouseServiceImpl.java // 查询试剂交易&#xff08;入库/出库&#xff09;记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...