sync.RWMutex和sync.Mutex有什么区别

news/2025/3/3 14:01:04/文章来源:https://www.cnblogs.com/maidongdong/p/18748066

在 Go 语言中,sync.Mutexsync.RWMutex 都是用于同步的工具,用于在并发环境下保护共享资源。它们的区别主要在于功能和使用场景sync.Mutex 是普通的互斥锁,而 sync.RWMutex 是读写锁,提供了更细粒度的控制。以下是详细对比和解释:


1. 基本概念

  • sync.Mutex(互斥锁):

    • 全称是“互斥锁”(Mutual Exclusion Lock)。
    • 一次只能被一个 goroutine 持有,任何其他尝试获取锁的 goroutine 都会被阻塞,直到锁被释放。
    • 适用于读写都需要独占访问的场景。
  • sync.RWMutex(读写锁):

    • 全称是“读写互斥锁”(Read-Write Mutex)。
    • 区分了读操作和写操作:
      • 读锁(RLock):允许多个 goroutine 同时获取读锁(并发读)。
      • 写锁(Lock):一次只能被一个 goroutine 持有,且写锁会阻塞所有读锁和写锁(独占写)。
    • 适用于读多写少的场景。

2. 方法

  • sync.Mutex

    • Lock():加锁,锁定后其他 goroutine 无法访问资源。
    • Unlock():解锁,释放锁后其他 goroutine 可以竞争获取锁。
    • 只有这两种状态:锁定或未锁定。
  • sync.RWMutex

    • Lock():加写锁,独占访问,阻塞所有读锁和写锁。
    • Unlock():解写锁,释放写锁。
    • RLock():加读锁,允许多个 goroutine 同时持有读锁。
    • RUnlock():解读锁,释放读锁。
    • 提供了读和写的分离控制。

3. 并发行为

  • sync.Mutex

    • 无论读还是写,所有操作都必须排队,同一时间只有一个 goroutine 可以访问资源。
    • 并发性低:即使是只读操作,也会被阻塞。
  • sync.RWMutex

    • 读并发:多个 goroutine 可以同时持有读锁(RLock),只要没有写锁。
    • 写独占:写锁(Lock)会阻塞所有读锁和写锁,直到写锁释放。
    • 读写互斥:读锁和写锁不能同时存在。
    • 并发性高:允许多个读操作并行执行。

4. 适用场景

  • sync.Mutex

    • 适合读写操作频率差不多,或者资源访问模式简单的场景。
    • 例如:需要严格顺序执行的操作(如计数器增减、单一资源修改)。
  • sync.RWMutex

    • 适合读多写少的场景。
    • 例如:数据库查询(大量并发读取,偶尔更新)、缓存读取(频繁读,偶尔写)。

5. 性能对比

  • sync.Mutex

    • 实现简单,开销较低,但并发性能受限,因为所有操作都串行化。
    • 在高并发读场景下效率较低。
  • sync.RWMutex

    • 实现更复杂,开销略高于 sync.Mutex(因为需要区分读写状态)。
    • 在读多写少的场景下性能更好,因为允许多个读操作并发执行。

6. 示例代码

使用 sync.Mutex

package mainimport ("fmt""sync"
)func main() {var mu sync.Mutexcounter := 0var wg sync.WaitGroup// 10 个 goroutine 并发增减for i := 0; i < 10; i++ {wg.Add(1)go func() {defer wg.Add(-1)mu.Lock()counter++fmt.Println(counter)mu.Unlock()}()}wg.Wait()fmt.Println("Final counter:", counter)
}
  • 结果:每次只有一个 goroutine 修改 counter,最终结果是 10。
  • 特点:所有操作串行执行。

使用 sync.RWMutex

package mainimport ("fmt""sync"
)func main() {var rwmu sync.RWMutexdata := map[string]int{"key": 0}var wg sync.WaitGroup// 5 个读 goroutinefor i := 0; i < 5; i++ {wg.Add(1)go func() {defer wg.Add(-1)rwmu.RLock()           // 加读锁fmt.Println(data["key"])rwmu.RUnlock()         // 解读锁}()}// 1 个写 goroutinewg.Add(1)go func() {defer wg.Add(-1)rwmu.Lock()            // 加写锁data["key"] = 42rwmu.Unlock()          // 解写锁}()wg.Wait()fmt.Println("Final value:", data["key"])
}
  • 结果:多个读操作可以并发执行,但写操作会等待所有读锁释放,最终 data["key"] 为 42。
  • 特点:读并发,写独占。

7. 关键区别总结

特性 sync.Mutex sync.RWMutex
锁类型 互斥锁 读写锁
并发读 不支持(串行) 支持(多个读锁可并存)
并发写 不支持(独占) 不支持(写锁独占)
读写互斥 不区分读写,全部互斥 读锁和写锁互斥
方法 Lock, Unlock Lock, Unlock, RLock, RUnlock
复杂度 简单 稍复杂
性能 读写均衡时较优 读多写少时更优
适用场景 简单同步 高并发读、少写场景

8. 选择建议

  • 如果你的程序读写操作频率差不多,或者逻辑简单,使用 sync.Mutex 即可。
  • 如果读操作远远多于写操作,且希望提升并发性能,使用 sync.RWMutex 更合适。
  • 如果需要更高级的并发控制(例如不需要手动锁),可以考虑 sync.Map 或其他并发数据结构。

如果你有具体场景想讨论(比如如何在某个代码中选择锁),告诉我,我可以帮你进一步分析!

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

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

相关文章

记一次.NET内存居高不下排查解决与启示

.NET内存居高不下排查解决过程与启示前情 我们有个海外的项目,一共70个服务,前前后后花了超过一年时间完成了云服务迁移和架构调整。主要是架构调整了,原来的docker swarm托管服务,新架构改为Kubernetes托管。几台云服务器将n个服务堆在一起,只会对服务器资源做监控。新架…

NTDLL 解除挂钩介绍

一、介绍 NTDLL 解除挂钩是将加载进程中的钩子 DLL 替换为未更改的未钩子版本,用未挂钩的版本替换挂钩的 DLL 需要手动设置 IAT、修复重新分配和其他繁琐的任务。为了避免这种情况, .text 可以替换 DLL 的一部分,特别是包含挂钩的部分。文本部分包含 DLL 的导出函数代码,这…

SFDC记录保存顺序完整版本(Spring25版本)

SFDC记录保存顺序完整版本(Spring25版本) 前言 Salesforce在记录保存过程有一套执行顺序,并且Apex是不可以打断点的,所以掌握这个顺序对我们排查问题定位问题所在位置很有帮助,也是每个开发人员都应该掌握的知识。 正文 When you save a record with an insert, update, or…

驾驶员监控系统DMS

目前,随着整车智能化的深入发展、L2及L2+的高级辅助驾驶功能加速上车,L3级别的自动驾驶也在快速落地中。与此同时,交通事故的频发也引发着行业的重视。这一情况通常与人类不良驾驶行为息息相关:疲劳驾驶、分心驾驶、危险驾驶等交通安全“隐形杀手”长期威胁驾驶员与乘客的生…

【CDN理论基础】http的正向代理与反向代理及http缓存原理

一、HTTP代理协议 HTTP代理的工作原理是在客户端和web服务器之间拦截和转发HTTP请求和响应。换句话说,当您尝试使用HTTP代理访问某个网站或服务时,您并没有直接与web服务器通信,而是由代理帮你去跟web服务器交互,将你的请求转发给web服务器,再将web服务器返回的内容再转发…

[译] DeepSeek开源smallpond开启DuckDB分布式之旅

DeepSeek 正通过 smallpond(一种新的、简单的分布式计算方法)推动 DuckDB 超越其单节点的局限。然而,我们也需要探讨,解决了横向扩展的挑战后,会不会是带来新的权衡问题呢?译者序:DuckDB 是一款基于 PostgreSQL 语法生态的分析型嵌入式数据库,是近年来数据库圈的新秀,…

2025 联合省选流水账(公开版)

Remain loving. Keep dreaming.2025 联合省选流水账(公开版) 前言 写流水账是为了知道我每天干了什么。 2.3 春节假期结束,该上课了。 如果没有进队,就去学文化课,如果进了队,就晚一点去学文化课。 人,别摆了。 2.4 下午在水 B 站,晚上去看花灯了。 2.5 晚上收拾行李。…

3.4K star!全能PDF处理神器开源!文档转换/OCR识别一键搞定

PDF-Guru 是一款开箱即用的全能型PDF处理工具,支持跨平台文档转换、智能OCR识别、多格式解析等核心功能。项目采用模块化架构设计,提供简洁的Web界面和API接口,开发者可快速集成到现有系统中。嗨,大家好,我是小华同学,关注我们获得“最新、最全、最优质”开源项目和高效工…

ICP备案注销

ICP备案注销教程服务器供应商:腾讯云

通过fetch_mcp,让Cline能够获取网页内容。

fetch_mcp介绍 GitHub地址:https://github.com/zcaceres/fetch-mcp此MCP服务器提供了以多种格式(包括HTML、JSON、纯文本和Markdown)获取网络内容的功能。 效果 以这个新闻页面为例:获取页面的Html效果:获取页面文本效果:获取md格式内容并保存到test.md效果:是不是很有帮…

index.aspx ,add的重复集合项

原因:地址错误,缺少index.aspx 正确地址:127.0.0.1/K3Cloud/mobile/index.aspx

【日记】周末基本都在睡觉呢(1215 字)

正文这个周末几乎什么都没做。昨天看了一点点内科学,不过主要还是在涩涩(笑)。目前进度停留在肺结核。肺结核之前过年的时候看过一点点,主要还是做笔记。如果不看,可能我一生都不知道七八成的人都有肺结核。我听到唐子益说这个结论的时候极其诧异。结核杆菌耐酸耐碱耐冷耐…