go sync包(三) 读写锁(二)

读写锁 RWMutex

写锁

加锁

RWMetex 的写锁复用了 Mutex

// Lock locks rw for writing.
// If the lock is already locked for reading or writing,
// Lock blocks until the lock is available.
func (rw *RWMutex) Lock() {if race.Enabled {_ = rw.w.staterace.Disable()}// First, resolve competition with other writers.// writer加锁rw.w.Lock()// Announce to readers there is a pending writer.// 反转 readerCount,告诉 reader 有writer竞争锁// Add(-rwmutexMaxReaders) 将 readerCount 置为负数,表示当前有 writer 竞争锁r := rw.readerCount.Add(-rwmutexMaxReaders) + rwmutexMaxReaders// Wait for active readers.// 当前有 reader 持有锁,writer 等待if r != 0 && rw.readerWait.Add(r) != 0 {runtime_SemacquireRWMutex(&rw.writerSem, false, 0)}if race.Enabled {race.Enable()race.Acquire(unsafe.Pointer(&rw.readerSem))race.Acquire(unsafe.Pointer(&rw.writerSem))}
}
解锁

解锁也是复用的 Mutex,区别在于解锁的时候会唤醒所有阻塞的 reader

// Unlock unlocks rw for writing. It is a run-time error if rw is
// not locked for writing on entry to Unlock.
//
// As with Mutexes, a locked RWMutex is not associated with a particular
// goroutine. One goroutine may RLock (Lock) a RWMutex and then
// arrange for another goroutine to RUnlock (Unlock) it.
func (rw *RWMutex) Unlock() {if race.Enabled {_ = rw.w.staterace.Release(unsafe.Pointer(&rw.readerSem))race.Disable()}// Announce to readers there is no active writer.// 反转 readerCount,告诉 reader 没有 writer 竞争锁r := rw.readerCount.Add(rwmutexMaxReaders)if r >= rwmutexMaxReaders {race.Enable()fatal("sync: Unlock of unlocked RWMutex")}// Unblock blocked readers, if any.// 唤醒所有阻塞的 readerfor i := 0; i < int(r); i++ {runtime_Semrelease(&rw.readerSem, false, 0)}// Allow other writers to proceed.// writer 解锁rw.w.Unlock()if race.Enabled {race.Enable()}
}

读锁

加锁
// RLock locks rw for reading.
//
// It should not be used for recursive read locking; a blocked Lock
// call excludes new readers from acquiring the lock. See the
// documentation on the RWMutex type.
func (rw *RWMutex) RLock() {if race.Enabled {_ = rw.w.staterace.Disable()}// writer 加锁时,readerCount 是负数// 写锁优先级比读锁高,reader 休眠// 如果 reader+1 > 0, 当前加了读锁if rw.readerCount.Add(1) < 0 {// A writer is pending, wait for it.runtime_SemacquireRWMutexR(&rw.readerSem, false, 0)}if race.Enabled {race.Enable()race.Acquire(unsafe.Pointer(&rw.readerSem))}
}
解锁
// RUnlock undoes a single RLock call;
// it does not affect other simultaneous readers.
// It is a run-time error if rw is not locked for reading
// on entry to RUnlock.
func (rw *RWMutex) RUnlock() {if race.Enabled {_ = rw.w.staterace.ReleaseMerge(unsafe.Pointer(&rw.writerSem))race.Disable()}// 有等待的 writerif r := rw.readerCount.Add(-1); r < 0 {// Outlined slow-path to allow the fast-path to be inlinedrw.rUnlockSlow(r)}if race.Enabled {race.Enable()}
}func (rw *RWMutex) rUnlockSlow(r int32) {if r+1 == 0 || r+1 == -rwmutexMaxReaders {race.Enable()fatal("sync: RUnlock of unlocked RWMutex")}// A writer is pending.// 读锁全部解锁完毕,唤醒 writerif rw.readerWait.Add(-1) == 0 {// The last reader unblocks the writer.runtime_Semrelease(&rw.writerSem, false, 1)}
}

小结

  • sync.RWMutex 复用 sync.Mutex
  • 写锁:
    • 加锁时 writer 反转 readerCount 置为负数,如果当前有 reader 正在执行, readerCount 赋值给 readerWait,writer 休眠。
    • 解锁时 writer 反转 readerCount 置为正常,并唤醒所有阻塞的 reader。
  • 读锁:
    • 加锁时 readerCount + 1,如果 readerCount < 0,reader 阻塞。
    • 解锁时 readerCount - 1,如果 readerCount < 0,readerWait - 1,当 readerWait == 0 时,唤醒 writer。

sync.RWMutex 复用 sync.Mutex

  • 调用 sync.RWMutex.Lock 尝试获取写锁时;
  • 每次 sync.RWMutex.RUnlock 都会将 readerCount 其减一,当它归零时该 Goroutine 会获得写锁;
  • 将 readerCount 减少 rwmutexMaxReaders 个数以阻塞后续的读操作;

调用 sync.RWMutex.Unlock 释放写锁时,会先通知所有的读操作,然后才会释放持有的互斥锁;

读写互斥锁在互斥锁之上提供了额外的更细粒度的控制,能够在读操作远远多于写操作时提升性能。

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

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

相关文章

Selenium 选择器定位元素方式详解

Selenium 选择器定位元素方式详解 在自动化测试中&#xff0c;定位网页元素是一个至关重要的步骤。Selenium 提供了多种选择器来帮助我们精确地找到页面上的元素。以下将详细介绍各种选择器的用法和区别&#xff0c;包括 ID、XPATH、LINK_TEXT、PARTIAL_LINK_TEXT、NAME、TAG_…

将Windows11右键菜单修改为Windows10风格

Windows11更新后&#xff0c;右键菜单很多功能隐藏起来了&#xff0c;使用时需要点击“显示更多选型”才能获取完整功能。为了能获得Windows10右键菜单丝滑的体验&#xff0c;我总结了以下方法。 方法一&#xff1a;控制台操作法 按住winR打开运行窗口 输入cmd&#xff0c;…

区间问题——905. 区间选点

目录 区间问题 定义 运用情况 注意事项 解题思路 AcWing 905. 区间选点 题目描述 运行代码 代码思路 改进思路 其它代码 代码思路 区间问题 定义 区间通常是指一个连续的范围&#xff0c;可以用数轴上的一段来表示。 运用情况 在数学中广泛用于表示变量的取值范…

未系安全带智能监测摄像机

未系安全带智能监测摄像机在现代安全管理中发挥着至关重要的作用。这些先进设备不仅仅是简单的监视工具&#xff0c;更是通过整合高级技术来提升工作效率和安全性&#xff0c;特别是在需要高度警惕的作业环境中尤为突出。 首先&#xff0c;这些智能监测摄像机配备了精准的视觉识…

SOLIDWORKS专业版2024价格

SOLIDWORKS Professional 专业版&#xff0c;带有 ECAD/MCAD 协作、自动成本估算、协作功能、设计和工程图检查、复杂的零部件库以及高级真实感渲染。 1. ECAD/MCAD协作&#xff1a;SOLIDWORKS专业版提供了强大的ECAD/MCAD协作功能&#xff0c;使得设计团队可以更高效地进行跨…

HTML(23)——垂直对齐方式

垂直对齐方式 属性名&#xff1a;vertical-align 属性值效果baseline基线对齐(默认)top顶部对齐middle居中对齐bottom底部对齐 默认情况下浏览器对行内块&#xff0c;行内标签都按文字处理&#xff0c;默认基线对齐 导致图片看起来会偏上&#xff0c;文字偏下。 示例&#…

帝国cms定时审核并更新的方法

比如你网站采集了成千上万篇文章,不可能一下子全部放出来的,所以为了模拟人工发布,那么就需要定时审核发布文章内容,本文内容核心解决了更加个性化的逼真模拟人工更新网站内容。 第一:首先要满足你的表中有未审核的数据 第二:到http://bbs.phome.net/showthread-31-19616…

谷歌浏览器截图

一 右击&#xff0c;然后点击检查&#xff1b; 二 然后ctrlshiftp,运行命令&#xff1b; 三 3.1搜索截图&#xff1a; 如果你设置为中文&#xff0c;搜索截图&#xff0c;选择你想要的截图类型&#xff1b; 如果你是在英文情况下&#xff1a; 输入capture full size 来过滤…

【Redis】如何保证缓存和数据库的一致性

目录 背景问题思路 三个经典的缓存模式Cache-Aside读缓存写缓存为什么是删除旧缓存而不是更新旧缓存&#xff1f;为什么不先删除旧的缓存&#xff0c;然后再更新数据库&#xff1f; 延迟双删如何确保原子性 Read-Through/Write-ThroughRead-ThroughWrite-Through Write Behind …

【九】【QT开发应用】WebRTC的sigslot源码和使用WebRTC的sigslot使用编写信号槽

WebRTC&#xff08;Web Real-Time Communication&#xff09; 是一个开源项目&#xff0c;提供实时通信能力&#xff0c;广泛应用于视频、音频和数据传输。在WebRTC的实现中&#xff0c;sigslot库用于信号和槽机制&#xff0c;以实现事件驱动的编程模型。 WebRTC的sigslot部分…

电子盖章怎么做_电子盖章软件

使用e-章宝&#xff08;易友EU3000智能盖章软件&#xff09;进行电子盖章的步骤如下&#xff1a; 一、准备阶段 软件获取&#xff1a; 访问e-章宝&#xff08;易友EU3000智能盖章软件&#xff09;的官方网站或相关渠道&#xff0c;下载并安装软件。账户注册与登录&#xff1a…

HTML常用标签简明汇总

常见标签 标签写法介绍<! – – >注释&#xff0c;内容不会在页面显示< h1 >< /h1 >标题&#xff08;只有1到6的标题等级&#xff09;< p >< /p>段落 独占一行< a href“网址”>< /a>超链接 用href 后面接网址< br >换行<…

泰迪智能科技大数据人工智能实训室优势特色介绍

泰迪智能科技大数据人工智能实训室是面向人工智能技术应用、大数据技术、软件技术专业&#xff0c;是一个教、学、培训认证统一的实训平台&#xff0c;集教学、实训、培训认证功能于一体&#xff0c;围绕人工智能主题&#xff0c;同时兼顾当前IT流行技术的发展趋势&#xff0c;…

注册机CAD2020激活遇到激活错误 0015.111的解决办法

这里写自定义目录标题 注册机下载位置破解要点 注册机下载位置 https://download.csdn.net/download/Stephen___Qin/89476691 破解要点 1.要以管理员身份运行CAD2020软件和注册机 2.要先点击注册的patch&#xff08;中文版本为“补丁”&#xff09;按键

Linux tcpdump抓包必备知识

author: 放牛娃学编程 moto: 分享与热爱&#xff0c;不是大爱我不说 放牛娃每日一语: 除了你自己&#xff0c;没有人可以说你不行 别急着划开&#xff0c;这篇笔记一定能够给你带来收获 因为这里你能学到AI永远也给不了你的知识 Linux tcpdump抓包必备知识 文章目录 Linux tcp…

Softing “Ethernet-APL现场交换机”亮相ACHEMA 2024

Softing工业在ACHEMA 2024上展示了新的“aplSwitch Field”。作为一个先进的16端口以太网高级物理层&#xff08;Ethernet-APL&#xff09;现场交换机&#xff0c;它配有可选的PROFIBUS Process Automation&#xff08;PA&#xff09;代理&#xff0c;适用于Zone 2环境&#xf…

期待一年后人工智能的飞跃:从高中生到博士的智力水平

关于ChatGPT本身&#xff0c;可以分享一些普遍讨论的优缺点及可能的发展方向&#xff1a; ChatGPT的优点&#xff1a; 对话理解能力强大&#xff1a;能够理解复杂和多轮对话上下文&#xff0c;提供连贯且相关的回复。生成内容丰富多样&#xff1a;能根据要求生成故事、诗歌、…

JavaWeb系列二十: jQuery的DOM操作 下

jQuery的DOM操作 CSS-DOM操作多选框案例页面加载完毕触发方法作业布置jQuery获取选中复选框的值jQuery控制checkbox被选中jQuery控制(全选/全不选/反选)jQuery动态添加删除用户 CSS-DOM操作 获取和设置元素的样式属性: css()获取和设置元素透明度: opacity属性获取和设置元素高…

数字化营销与传统营销的完美协奏曲!

在这个数字化的时代&#xff0c;营销的世界正在发生着巨大的变革&#xff01;数字化营销如火箭般崛起&#xff0c;但传统营销也并未过时。那么&#xff0c;如何让它们携手共进&#xff0c;创造出无与伦比的营销效果呢&#xff1f;今天&#xff0c;就让我们讲述一下蚓链数字化营…

【Rust】——所有可能会用到模式的位置

&#x1f4bb;博主现有专栏&#xff1a; C51单片机&#xff08;STC89C516&#xff09;&#xff0c;c语言&#xff0c;c&#xff0c;离散数学&#xff0c;算法设计与分析&#xff0c;数据结构&#xff0c;Python&#xff0c;Java基础&#xff0c;MySQL&#xff0c;linux&#xf…