go map fatal error: concurrent map iteration and map write 读写锁与深度拷贝的坑
起因
从币安实时拉取交易对的数据,这里使用了 map,用于存放每个交易对的最新价格,由于 map 并不是并发安全的所以加了读写锁。
但系统有时候还是会发生 fatal error: concurrent map iteration and map write 错误
使用代码如下:
type BinanceSymbolPrice struct {
Item map[string]SymbolPrice
Lock sync.RWMutex
}
func NewSymbolPrice() *BinanceSymbolPrice {
info := &BinanceSymbolPrice{
Item: make(map[string]SymbolPrice),
}
return info
}
/**
* 现货最新价格行情操作
*/
func (bst *BinanceSymbolPrice) GetAllSymbolPriceInfo() map[string]SymbolPrice {
bst.Lock.RLock()
defer bst.Lock.RUnlock()
return bst.Item
}
func (bst *BinanceSymbolPrice) GetSymbolPriceInfo(symbol string) SymbolPrice {
bst.Lock.RLock()
defer bst.Lock.RUnlock()
info, exist := bst.Item[symbol]
if !exist {
return SymbolPrice{}
}
return info
}
func (bst *BinanceSymbolPrice) AddSymbolPriceItem(symbol string, SymbolPrice SymbolPrice) {
bst.Lock.Lock()
defer bst.Lock.Unlock()
if _, ok := bst.Item[symbol]; ok {
return
}
bst.Item[symbol] = SymbolPrice
}
func (bst *BinanceSymbolPrice) DelSymbolPriceInfo(symbol string) {
bst.Lock.Lock()
defer bst.Lock.Unlock()
if _, ok := bst.Item[symbol]; !ok {
return
}
delete(bst.Item, symbol)
}
// 更新交易对价格
func (bst *BinanceSymbolPrice) ResetSymbolPriceInfo(symbol string, SymbolPrice SymbolPrice) {
bst.Lock.Lock()
defer bst.Lock.Unlock()
bst.Item[symbol] = SymbolPrice
}
分析
经过自己写测试文件,才找出来问题的原因,问题代码如下
func (bst *BinanceSymbolPrice) GetAllSymbolPriceInfo() map[string]SymbolPrice {
bst.Lock.RLock()
defer bst.Lock.RUnlock()
return bst.Item
}
这段代码的含义是取出map中的所有数据,咋一看没什么问题,可是忽略了 map 是引用类型,这样实际上传递的是地址,还是会对源数据进行访问,从而造成了 map 读写并发。
修改如下:
func (bst *BinanceSymbolPrice) GetAllSymbolPriceInfo() map[string]SymbolPrice {
bst.Lock.RLock()
defer bst.Lock.RUnlock()
item := make(map[string]SymbolPrice)
for key, value := range bst.Item {
item[key] = value
}
return item
}
新初始化声明了一个新 map ,把查询出来的数据重新copy到新的map中,这样再使用时,访问到的数据就不再是同一份数据了,从而避免了 map 读写并发。
在Go语言1.9版本后提供了一种并发安全的 map,sync.Map 推荐大家使用。
这篇文章解释了如何使用 go sync.map的使用
go map fatal error: concurrent map iteration and map write 读写锁与深度拷贝的坑的更多相关文章
- golang map 读写锁与深度拷贝的坑
0X01 golang中,map(字典)无法并发读写 简单来说,新建万条线程对同一个map又读又写,会报错. 为此,最好加锁,其实性能影响并不明显. type taskCache struct{ sy ...
- 深入理解java:2.3.2. 并发编程concurrent包 之重入锁/读写锁/条件锁
重入锁 Java中的重入锁(即ReentrantLock) 与JVM内置锁(即synchronized)一样,是一种排它锁. ReentrantLock提供了多样化的同步,比如有时间限制的同步(定 ...
- golang fatal error: concurrent map read and map write
调试程序的时候,为了打印map中的内容 ,直接 使用seelog 的方法打印 map中的内容到日志,结果出现 “concurrent map read and map write”的错误,导致程序异常 ...
- Golang map并发 读写锁
golang并发 一:只有写操作 var ( count int l = sync.Mutex{} m = make(map[int]int) ) //全局变量并发写 导致计数错误 func vari ...
- BUG:给Nexus7编译Android4.2的时候出现 fatal error: map: No such file or directory
情况是这样的,某人最近入手一台nexus7,于是在cyanogenmod 将nexus7的原代码下载到本地,编译环境是UBUNTU 12,04 然后编译的时候,出现了如下的错误导致编译失败 <p ...
- ObjectARX2012错误1 fatal error C1083: 无法打开包括文件:“arxHeaders.h”: No such file or directory; fatal error C1083: 无法打开包括文件:“map”: No such file or directory
问题1:fatal error C1083: 无法打开包括文件:“arxHeaders.h”: No such file or directory: 解决办法:这个问题很明显,是因为没有在工程属性里包 ...
- vcftools报错:Writing PLINK PED and MAP files ... Error: Could not open temporary file.解决方案
一般来说有两种解决方案. 第一种:添加“--plink-tped”参数: 用vcftools的“--plink”参数生成plink格式文件时,小样本量测试可以正常生成plink格式,用大样本量时产生W ...
- Java:concurrent包下面的Map接口框架图(ConcurrentMap接口、ConcurrentHashMap实现类)
Java集合大致可分为Set.List和Map三种体系,其中Set代表无序.不可重复的集合:List代表有序.重复的集合:而Map则代表具有映射关系的集合.Java 5之后,增加了Queue体系集合, ...
- 【ActiveMQ】管理界面查看消息详情,报错/WEB-INF/tags/form/forEachMapEntry.tag PWC6199: Generated servlet error: The type java.util.Map$Entry cannot be resolved. It is indirectly referenced from required .class files
ActiveMQ版本:5.12 JDK版本:1.8 ===================== 使用ActiveMQ过程中,在管理界面查看消息详情,发现报错: 查看日志信息,报错如下: 2017-11 ...
- angular4 JavaScript内存溢出问题 (FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory)
最近在写基于angular4的项目的时候,在build --prod的时候,突然措手不及的蹦出个报错,大致错误如下: 70% building modules 1345/1345 modules 0 ...
随机推荐
- Qt编写安防视频监控系统49-多数据库支持
一.前言 数据库设置模块,因为很多项目都会用到,索性这期间也将这玩意重新架构了一遍,对应的数据库组件同样重写了一遍,关于数据库的参数无非就6个,数据库类型(sqlite.mysql等).数据库名称.主 ...
- 一篇文章弄懂 JavaScript 中通过import导入模块的原理
原文链接: 1.import 2.彻底理解JavaScript ES6中的import和export 3.JavaScript ES6中export.import与export default的用法和 ...
- 查看Android是否开机启动进入桌面
adb 或者 串口终端 getprop sys.boot_completed 返回空代表没有进入桌面返回1代表已进入桌面
- github-链接地址
------------------------------------------------------ https://github.com/seata https://github.com/a ...
- Linux服务器上shell脚本批量循环测试接口连通性,bash工具循环测试curl性能
使用curl的-w选项来输出各种时间信息 -o /dev/null 用于丢弃响应体,只关心头部信息 -s 用于静默模式,不输出进度信息 %{http_code} 输出HTTP状态码 %{time_na ...
- nginx里面的路径定位关键词root、alias
nginx里面的路径定位关键词root.alias是有区别的: 设置请求资源的目录root / alias root:设置请求的根目录 语法 root path; 默认值 root html; 位置 ...
- 0425-字节输入流FileInputStream
package A10_IOStream; import java.io.FileInputStream; import java.io.IOException; /* java.io.InputSt ...
- 开源标杆!天翼云TeleDB入选《2024央国企开源项目典型实践》!
近日,由中国通信标准化协会主办.中国信通院承办的2024 OSCAR开源产业大会在北京召开,会上发布<2024央国企开源项目典型实践>,天翼云科技有限公司打造的"TeleDB分布 ...
- Jenkins插件:Generic Webhook Trigger
Jenkins插件:Generic Webhook Trigger 作为一名软件测试工程师,在日常工作中,我经常需要使用Jenkins来进行持续集成和持续部署(CI/CD).而Jenkins的众多插件 ...
- Luogu P9606 CERC2019 ABB 题解 [ 绿 ] [ KMP ] [ 字符串哈希 ]
ABB:KMP 的做法非常巧妙. 哈希 思路 显然正着做一遍哈希,倒着做一遍哈希,然后枚举回文中心即可. 时间复杂度 \(O(n)\). 代码 #include <bits/stdc++.h&g ...