go sync.map的使用
前言
数据竞争是并发情况下,存在多线程/协程读写相同数据的情况,必须存在至少一方写。另外,全是读的情况下是不存在数据竞争的。
Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的。
如果map由多协程同时读和写就会出现 fatal error:concurrent map read and map write的错误。这是因为map在Go语言并发编程中,如果仅用于读取数据时候是安全的,但是在读写操作的时候是不安全的,在Go语言1.9版本后提供了一种并发安全的,sync.Map是Go语言提供的内置map,不同于基本的map数据类型,所以不能像操作基本map那样的方式操作数据,他提供了特有的方法,不需要初始化操作实现增删改查的操作。
需要并发读写时,一般的做法是加锁,但这样性能并不高,Go语言在 1.9 版本中提供了一种效率较高的并发安全的 sync.Map,sync.Map 和 map 不同,不是以语言原生形态提供,而是在 sync 包下的特殊结构。
sync.Map 特性
无须初始化,直接声明即可。
sync.Map 不能使用 map 的方式进行取值和设置等操作,而是使用 sync.Map 的方法进行调用,Store 表示存储,Load 表示获取,Delete 表示删除。
使用 Range 配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值,Range 参数中回调函数的返回值在需要继续迭代遍历时,返回 true,终止迭代遍历时,返回 false。
sync.Map提供的常用方法有如下七个:
- Load(key interface{}) (value interface{},ok bool):通过参数key查询对应的value,如果不存在则返回nil;ok表示是否找到对应的值。
- Store(key,value interface{}):该方法相当于对sync.Map的更新或新增,参数是键值对。
- LoadOrStore(key,value interface{}) (actual interface{},loaded bool):该方法的参数为key和value。该方法会先根据参数key查找对应的value,如果找到则不修改原来的值并通过actual返回,并且loaded为true;如果通过key无法查找到对应的value,则存储key-value并且将存储的value通过actual返回,loaded为false。
- Delete(key interface{}):通过key删除键值对。
- LoadAndDelete(key interface{}):通过key删除键的值,如果有,则返回上一个值。
- Range(f func(key,value interface{}) bool):遍历sync.Map的元素,注意for...range map是对内置map类型的用法,sync.Map需要使用单独的Range方法。
并发安全的 sync.Map 演示代码如下:
package main
import (
"fmt"
"sync"
)
//声明sync.Map
var syncmap sync.Map
func main() {
//Store方法将键值对保存到sync.Map
syncmap.Store("zhangsan", 97)
syncmap.Store("lisi", 100)
syncmap.Store("wangmazi", 200)
// LoadOrStore key不存在
v, ok := syncmap.LoadOrStore(3, "three")
fmt.Println(v, ok) // three false
// LoadOrStore key存在
v, ok = syncmap.LoadOrStore(1, "thisOne")
fmt.Println(v, ok) // one ture
// Load方法获取sync.Map 键所对应的值
fmt.Println(syncmap.Load("lisi"))
// Delete方法键删除对应的键值对
syncmap.Delete("lisi")
var syncmap sync.Map
// LoadAndDelete key不存在
v, ok := syncmap.LoadAndDelete("xiaomi")
fmt.Println(v, ok) // <nil> false
syncmap.Store("xiaomi", "xiaomi")
// LoadAndDelete key存在
v, ok = syncmap.LoadAndDelete("xiaomi")
fmt.Println(v, ok) // xiaomi true
// Range遍历所有sync.Map中的键值对
syncmap.Range(func(k, v interface{}) bool {
fmt.Println(k, v)
return true
})
}
注意
声明 score,类型为 sync.Map,注意,sync.Map 不能使用 make 创建。
将一系列键值对保存到 sync.Map 中,sync.Map 将键和值以 interface{} 类型进行保存。
Range() 方法可以遍历 sync.Map,遍历需要提供一个匿名函数,参数为 k、v,类型为 interface{},每次 Range() 在遍历一个元素时,都会调用这个匿名函数把结果返回。
sync.Map 没有提供获取 map 数量的方法,替代方法是在获取 sync.Map 时遍历自行计算数量,sync.Map 为了保证并发安全有一些性能损失,因此在非并发情况下,使用 map 相比使用 sync.Map 会有更好的性能。
go sync.map的使用的更多相关文章
- Go 1.9 sync.Map揭秘
Go 1.9 sync.Map揭秘 目录 [−] 有并发问题的map Go 1.9之前的解决方案 sync.Map Load Store Delete Range sync.Map的性能 其它 在Go ...
- Golang:sync.Map
由于map在gorountine 上不是安全的,所以在大量并发读写的时候,会出现错误. 在1.9版的时候golang推出了sync.Map. sync.Map 通过阅读源码我们发现sync.Map是通 ...
- go的sync.Map
sync.Map这个数据结构是线程安全的(基本类型Map结构体在并发读写时会panic严重错误),它填补了Map线程不安全的缺陷,不过最好只在需要的情况下使用.它一般用于并发模型中对同一类map结构体 ...
- sync.Map(在并发环境中使用的map)
sync.Map 有以下特性: 需要并发读写时,一般的做法是加锁,但这样性能并不高,Go语言在 1.9 版本中提供了一种效率较高的并发安全的 sync.Map,sync.Map 和 map 不同,不是 ...
- sync.Map与Concurrent Map
1. sync.Map 1.1. map并发不安全 go1.6以后map有了并发的安全检查,所以如果在并发环境中读写map就会报错 func unsafeMap() { // 创建一个map对象 m ...
- golang 标准库 sync.Map 中 nil 和 expunge 区别
本文不是 sync.Map 源码详细解读,而是聚焦 entry 的不同状态,特别是 nil 状态和 expunge 状态的区分. entry 是 sync.Map 存放值的结构体,其值有三种,分别为 ...
- 图解Go里面的sync.Map了解编程语言核心实现源码
基础筑基 在大多数语言中原始map都不是一个线程安全的数据结构,那如果要在多个线程或者goroutine中对线程进行更改就需要加锁,除了加1个大锁,不同的语言还有不同的优化方式, 像在java和go这 ...
- 源码解读 Golang 的 sync.Map 实现原理
简介 Go 的内建 map 是不支持并发写操作的,原因是 map 写操作不是并发安全的,当你尝试多个 Goroutine 操作同一个 map,会产生报错:fatal error: concurrent ...
- 深度解密 Go 语言之 sync.map
工作中,经常会碰到并发读写 map 而造成 panic 的情况,为什么在并发读写的时候,会 panic 呢?因为在并发读写的情况下,map 里的数据会被写乱,之后就是 Garbage in, garb ...
- 深入理解golang:sync.map
疑惑开篇 有了map为什么还要搞个sync.map 呢?它们之间有什么区别? 答:重要的一点是,map并发不是安全的. 在Go 1.6之前, 内置的map类型是部分goroutine安全的,并发的读没 ...
随机推荐
- Qt音视频开发39-人脸识别在线版
一.前言 关于人脸识别这块,前些年不要太火,哪怕是到了今天依然火的一塌糊涂,什么玩意都要跟人脸识别搭个边,这东西应该只是人工智能的一个很小的部分,人脸识别光从字面上理解就是识别出人脸区域,其实背后真正 ...
- Ant入门简单实例
一.构建ant环境 要使用ant首先要构建一个ant环境,步骤很简单: 1) 安装jdk,设置JAVA_HOME ,PATH ,CLASS_PATH(这些应该是看这篇文章的人应该知道的) 2) 下载a ...
- KMS for Office 2021
I. 镜像下载 官方镜像下载地址: Office 2021 专业增强版: https://officecdn.microsoft.com/pr/492350f6-3a01-4f97-b9c0-c7c6 ...
- spark (一) 入门 & 安装
目录 基本概念 spark 核心模块 spark core (核心) spark sql (结构化数据操作) spark streaming (流式数据操作) 部署模式 local(本地模式) sta ...
- (四).NET6.0程序部署到Docker上
1.确保安装Docker 2.把需要部署到Docker上面的项目,咱们先添加Docker的支持,启动项目右键 -> 添加 -> Docker支持,选择 Linux 然后会自动生成Docke ...
- 还不会 Cert Manager 自动签发证书?一文掌握
相信很多小伙伴对于 Cert Manager 不陌生,Cert Manager 是 Kubernetes 上的证书管理工具,基于 ACME 协议与 Let's Encrypt 签发免费证书并为证书自动 ...
- C# 开发电子印章制作工具 -- 附下载程序
前言 本人在业余时间,开发了一款电子印章制作软件.印章制作软件看似简单,其实不然. 比如对椭圆形印章而言,要求公司名称中的每一个字间隔相等,要求字的方向与椭圆曲线垂直. 要满足这些条件,需要复杂的计算 ...
- JAVA常见问题合集
面向对象 面向过程和面向对象 面向对象的三大基本特征:封装.继承.多态 - 封装:隐藏内部细节 继承:复用现有代码 多态:改写对象行为 JAVA为什么是面向对象的,为什么还用int等基础类型 面向对象 ...
- SpringBoot启动报错:HikariPool-1 - Exception during pool initialization.
不说废话,直接上错误信息: 2020-06-23 10:48:19.899 INFO 10608 --- [ main] cn.wps.ep.account.sync.Application : St ...
- nvme磁盘故障注入方法
本文分享自天翼云开发者社区<nvme磁盘故障注入方法>,作者:曹****飞 在存储系统中,磁盘的故障是很可能出现的问题.存储软件的设计需要对故障进行处理,提高系统的健壮性.然而磁盘的故障是 ...