golang sync.Map 与使用普通的 map 的区别

golang,sync,map · 浏览次数 : 0

小编点评

本文主要探讨了sync.Map与普通Go map之间的几个关键区别,包括并发安全性、性能、使用场景以及示例对比。最后指出了在编写代码时应该遵循的原则以确保正确的并发处理。 1. **并发安全性**:普通map在无外部同步的情况下不具备并发安全性,可能导致数据竞争和未定义行为。而sync.Map通过其内部的同步机制,保证了多goroutine同时访问时的并发安全性。 - 普通map的问题所在 - sync.Map的并发安全性优势 2. **性能差异**:对于单线程或同步控制下的访问,普通map的性能通常优于sync.Map,因为它避免了额外的同步开销。然而,在高并发且读多写少的场景下,sync.Map的性能损失相对较小。 - 普通map在同步控制下的性能优势 - sync.Map在高并发下的性能考虑 3. **使用场景**:普通map适用于单线程环境或在有明确同步控制的多个goroutine环境中。而sync.Map适用于需要多goroutine共享数据且无需显式锁控制的场景,尤其是读操作远多于写操作的场景。 - 普通map的应用场景 - sync.Map适合的场景 4. **示例对比**:通过一个实际的GitHub仓库案例,展示了如何选择使用map还是sync.Map以满足特定需求。 - 示例仓库描述 - 案例分析 总的来说,选择使用map还是sync.Map取决于具体的应用场景和需求。在需要确保并发安全性的情况下,应优先选择sync.Map;而在对性能有较高要求,尤其是读多写少场景下,应根据实际情况进行权衡。此外,编写代码时应遵循一定的原则,以保证正确的并发处理。

正文

 


使用sync.Map与普通的Go map主要有以下几点区别:

1. 并发安全性

  普通map: 在没有外部同步的情况下,不是并发安全的。在多goroutine访问时,如果没有适当的锁或其他同步机制保护,可能会导致数据竞争和未定义行为。

  sync.Map: 是并发安全的。它内部实现了必要的同步机制,允许多个goroutine同时读写而不会引发数据竞争问题。

2. 性能

  普通map: 对于单线程或同步控制下的访问,性能通常优于sync.Map,因为它避免了额外的同步开销。

  sync.Map: 由于其内部的读写锁和复杂的逻辑(如读写分离、延迟更新等),在并发访问下虽然保证了安全,但可能比直接操作普通map慢一些。不过,在高并发且读多写少的场景下,它的性能损失相对较小。

3. 使用场景

  普通map: 适用于单线程环境或在有明确同步控制(如使用Mutex手动加锁解锁)的多goroutine环境中。

  sync.Map: 适用于无须显式锁控制的多goroutine共享数据场景,比如作为缓存、计数器等,特别是在读远多于写的场景下表现更佳。

 

4. 示例对比
https://github.com/farwish/go-lab/blob/master/src/sync/map.go

在选择使用map还是sync.Map时,需要根据具体的应用场景权衡并发需求与性能要求。


【问题】
  m := new(sync.Map) 初始化后,能不使用 m.Store 而是 m["key"] = 1 写入?


答案是 不可以直接使用m["key"] = 1这种方式来写入sync.Map。
因为sync.Map并没有直接实现索引赋值操作,它不支持像普通map那样的直接通过索引操作来设置或获取键值对。
为了保证并发安全,sync.Map提供了特定的方法来进行读写操作,如Store, Load, LoadOrStore, Delete, 和 Range等。
如果你想类似地使用索引操作,你需要通过sync.Map提供的方法来间接实现。

 

Link:https://www.cnblogs.com/farwish/p/18242860

与golang sync.Map 与使用普通的 map 的区别相似的内容:

golang sync.Map 与使用普通的 map 的区别

使用sync.Map与普通的Go map主要有以下几点区别: 1. 并发安全性 普通map: 在没有外部同步的情况下,不是并发安全的。在多goroutine访问时,如果没有适当的锁或其他同步机制保护,可能会导致数据竞争和未定义行为。 sync.Map: 是并发安全的。它内部实现了必要的同步机制,允许

golang sync.Once 保证某个动作仅执行一次的机制

type Once struct { done atomic.Uint32 m Mutex } 这段代码是 Go 语言标准库中 sync 包的一部分,定义了一个 Once 类型。Once 类型用于确保某个函数只被执行一次。它包含一个 done 原子类型和一个 Mutex 互斥锁。 done 表示动作

Golang 切片作为函数参数传递的陷阱与解答

作者:林冠宏 / 指尖下的幽灵。转载者,请: 务必标明出处。 GitHub : https://github.com/af913337456/ 出版的书籍: 《1.0-区块链DApp开发实战》 《2.0-区块链DApp开发:基于公链》 例子 切片作为函数参数传递的是值 用来误导切片作为函数参数传递的

golang 所有关键字的列表及释义归类

golang 所有关键字的列表及释义归类,截至1.18版本。 [控制结构] if : 条件语句,基于布尔表达式的值决定是否执行特定的代码块。 else、 else if : 用在 if 语句之后,当条件表达式为假时执行的代码块。 switch : 多路选择语句,根据不同的情况执行不同的代码块。 ca

golang 泛型的格式写法

Go语言中的泛型(Generics)是在 Go 1.18 版本中引入的一个重要特性,它允许你编写可重用的代码,而不需要为每种数据类型重复编写相同的逻辑。 泛型通过参数化类型(type parameters)来实现,使得函数、方法、接口和结构体可以与多种类型一起工作。 下面详细介绍Go语言中泛型的基本

Golang channel底层是如何实现的?(深度好文)

Go语言为了方便使用者,提供了简单、安全的协程数据同步和通信机制,channel。那我们知道channel底层是如何实现的吗?今天k哥就来聊聊channel的底层实现原理。同时,为了验证我们是否掌握了channel的实现原理,本文也收集了channel的高频面试题,理解了原理,面试题自然不在话下。

Golang 依赖注入设计哲学|12.6K 的依赖注入库 wire

本文从“术”层面,讲述“依赖注入”的实现,带你体会其对于整洁架构 & DDD 等设计思想的落地,起到的支撑作用。

[golang]在Gin框架中使用JWT鉴权

什么是JWT JWT,全称 JSON Web Token,是一种开放标准(RFC 7519),用于安全地在双方之间传递信息。尤其适用于身份验证和授权场景。JWT 的设计允许信息在各方之间安全地、 compactly(紧凑地)传输,因为其自身包含了所有需要的认证信息,从而减少了需要查询数据库或会话存储

golang如何使用指针灵活操作内存?unsafe包原理解析

本文将深入探讨Golang中unsafe包的功能和原理。同时,我们学习某种东西,一方面是为了实践运用,另一方面则是出于功利性面试的目的。所以,本文还会为大家介绍unsafe 包的典型应用以及高频面试题。

golang reflect 反射机制的使用场景

Go语言中的 reflect 包提供了运行时反射机制,允许程序在运行时检查和操作任意对象的数据类型和值。 以下是 reflect 包的一些典型使用场景: 1. 动态类型判断与转换:当需要处理多种类型的变量且具体类型直到运行时才能确定时,可以使用反射来检查变量的实际类型,并在可能的情况下进行类型转换。