首页 > 其他分享 >Go语言sync.Map(在并发环境中使用的map)

Go语言sync.Map(在并发环境中使用的map)

时间:2023-02-19 20:33:39浏览次数:35  
标签:Map 遍历 map scene sync 并发

Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的。   下面来看下并发情况下读写 map 时会出现的问题,代码如下: // 创建一个int到int的映射 m := make(map[int]int) // 开启一段并发代码 go func() {     // 不停地对map进行写入     for {         m[1] = 1     } }() // 开启一段并发代码 go func() {     // 不停地对map进行读取     for {         _ = m[1]     } }() // 无限循环, 让并发程序在后台执行 for { } 运行代码会报错,输出如下: fatal error: concurrent map read and map write   错误信息显示,并发的 map 读和 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 演示代码如下: package main import (       "fmt"       "sync" ) func main() {     var scene sync.Map     // 将键值对保存到sync.Map     scene.Store("greece", 97)     scene.Store("london", 100)     scene.Store("egypt", 200)     // 从sync.Map中根据键取值     fmt.Println(scene.Load("london"))     // 根据键删除对应的键值对     scene.Delete("london")     // 遍历所有sync.Map中的键值对     scene.Range(func(k, v interface{}) bool {         fmt.Println("iterate:", k, v)         return true     }) } 代码输出如下: 100 true iterate: egypt 200 iterate: greece 97   代码说明如下: 第 10 行,声明 scene,类型为 sync.Map,注意,sync.Map 不能使用 make 创建。 第 13~15 行,将一系列键值对保存到 sync.Map 中,sync.Map 将键和值以 interface{} 类型进行保存。 第 18 行,提供一个 sync.Map 的键给 scene.Load() 方法后将查询到键对应的值返回。 第 21 行,sync.Map 的 Delete 可以使用指定的键将对应的键值对删除。 第 24 行,Range() 方法可以遍历 sync.Map,遍历需要提供一个匿名函数,参数为 k、v,类型为 interface{},每次 Range() 在遍历一个元素时,都会调用这个匿名函数把结果返回。   sync.Map 没有提供获取 map 数量的方法,替代方法是在获取 sync.Map 时遍历自行计算数量,sync.Map 为了保证并发安全有一些性能损失,因此在非并发情况下,使用 map 相比使用 sync.Map 会有更好的性能。

标签:Map,遍历,map,scene,sync,并发
From: https://www.cnblogs.com/cheyunhua/p/17135527.html

相关文章

  • SQLmap使用
    SQLmap使用只对sql注入进行测试参数详解Target:目标-usqlmap.py-u"http://43.136.41.84:8080/vulnerabilities/sqli/?id=1&Submit=Submit"-pid--cookie"PHPSE......
  • mapper-spring-boot-starter的使用
    <?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:s......
  • 【JDK特性】stream 里面的map和flatMap区别
    背景JDK8中,stream流程下的map就不多说了,很熟悉,flatmap倒是不是特别熟悉,map和flatMap的区别看一个例子:List<String>cityListOne=newArrayList<>();......
  • HashMap相关
    底层数据结构,1.7和1.8有什么区别1.7:数组+链表1.8:数组+(链表|红黑树)为什么要用红黑树当链表过长时查询效率太低,树化可以提高查询效率为什么不是一开始就用树,而是达到......
  • 【多线程与高并发】- synchronized锁的认知
    synchronized锁的认知......
  • MapReduce概述
    MapReduce是一种分布式运算程序的编程框架,是用户开发“基于hadoop数据分析应用”的核心框架。核心功能是用户编写的业务逻辑代码和系统自带的组件组合在一起,构成一个分布......
  • Elasticsearch索引优化指南:分片、副本、mapping和analyzer
    Elasticsearch是一个开源的分布式搜索引擎,它的数据存储和查询速度非常快。然而,在面对大规模的数据集和高并发访问时,Elasticsearch的性能也可能受到一些影响。为了最大程度地......
  • Map集合
    介绍 Map在Java⾥边是⼀个接⼝,常⻅的实现类有HashMap、LinkedHashMap、TreeMap和ConcurrentHashMap  内嵌类    Map是java中的接口,Map.Entry是Map的一......
  • Geospatial,Hyperloglog,BitMap
    geospatial:地理位置底层实现geoadd:添加 geopos:获取指定的经纬度 geodist georadius:获取指定位置的指定半径的数据 georadiusbymember:获取指定元素指......
  • vue中执行异步函数async和await的用法
    在开发中,可能会遇到两个或多个函数异步执行的情况,对于Vue中函数的异步函数执行做了一个小总结,如下:异步执行使用async和await完成created(){this.init()},methods:{......