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编写视频监控系统74-悬浮工具栏(半透明/上下左右位置/自定义按钮)
一.前言 在监控系统中一般在视频实时预览的时候,希望提供一个悬浮工具条,可以显示一些提示信息比如分辨率.码率.帧率,提供一堆快捷操作按钮,可以录像.抓拍.云台控制.关闭等操作,参考了国内很多监控厂商客 ...
- Qt通用方法及类库10
函数名 //获取保存的文件 static QString getSaveName(const QString &filter, QString defaultDir = QCoreApplic ...
- Qt编写地图综合应用20-多浏览器内核
一.前言 本人写Qt程序这么多年,比较喜欢支持多个Qt版本,尤其是钟情于支持任意Qt版本+任意系统+任意编译器,这句话说起来简单其实实现起来就不容易了,首先你得有个很多版本的测试环境,起码十几个Qt环 ...
- 即时通讯技术文集(第36期):《跟着源码学IM》系列专题 [共12篇]
为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第36 期. [-1-] 跟着源码学IM(一):手把手教你用Netty实现心跳机制.断线重连机制 ...
- 开源即时通讯IM框架MobileIMSDK的微信小程序端开发快速入门
一.理论知识准备 您需要对微信小程序开发有所了解: 1)真正零基础入门学习笔记系列 2)从零开始的微信小程序入门教程 3)最全教程:微信小程序开发入门详解 您需要对WebSocket技术有所了解: 1 ...
- Hugo 静态博客部署
I. 前提条件 1.1 安装 Hugo 1.1.1 Windows 1.下载 Hugo(建议下载扩展版):Hugo(github.com) 2.解压 Hugo 压缩包到指定目录. 3.[Win + R ...
- spark (六) RDD算子(operator)
目录 1 转换算子(transformer)(将旧的RDD包装成新RDD) 1.1 单值类型 1.1.1 map 1.1.2 mapPartition 1.1.3 mapPartitionsWithI ...
- w3cschool-Apache Kafka 教程
参考https://www.w3cschool.cn/apache_kafka/ Apache Kafka 基础 2021-07-27 16:23 更新 对于大数据,我们要考虑的问题有很多,首先海量数 ...
- Superset用户集成方案2
superset 认证分析 superset基于flask-appbuilder开发,security基于flask_appbuilder.security,翻阅其代码, 找到入口: superset ...
- 二叉树神级遍历算法:morris遍历算法
morris遍历的实质 建立一种机制,对于没有左子树的节点只到达一次,对于有左子树的节点会到达两次 morris遍历的实现原则 记作当前节点为cur. 如果cur无左孩子,cur向右移动(cur=cu ...