起因

从币安实时拉取交易对的数据,这里使用了 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版本后提供了一种并发安全的 mapsync.Map 推荐大家使用。

这篇文章解释了如何使用 go sync.map的使用

go map fatal error: concurrent map iteration and map write 读写锁与深度拷贝的坑的更多相关文章

  1. golang map 读写锁与深度拷贝的坑

    0X01 golang中,map(字典)无法并发读写 简单来说,新建万条线程对同一个map又读又写,会报错. 为此,最好加锁,其实性能影响并不明显. type taskCache struct{ sy ...

  2. 深入理解java:2.3.2. 并发编程concurrent包 之重入锁/读写锁/条件锁

    重入锁 Java中的重入锁(即ReentrantLock)   与JVM内置锁(即synchronized)一样,是一种排它锁. ReentrantLock提供了多样化的同步,比如有时间限制的同步(定 ...

  3. golang fatal error: concurrent map read and map write

    调试程序的时候,为了打印map中的内容 ,直接 使用seelog 的方法打印 map中的内容到日志,结果出现 “concurrent map read and map write”的错误,导致程序异常 ...

  4. Golang map并发 读写锁

    golang并发 一:只有写操作 var ( count int l = sync.Mutex{} m = make(map[int]int) ) //全局变量并发写 导致计数错误 func vari ...

  5. BUG:给Nexus7编译Android4.2的时候出现 fatal error: map: No such file or directory

    情况是这样的,某人最近入手一台nexus7,于是在cyanogenmod 将nexus7的原代码下载到本地,编译环境是UBUNTU 12,04 然后编译的时候,出现了如下的错误导致编译失败 <p ...

  6. 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: 解决办法:这个问题很明显,是因为没有在工程属性里包 ...

  7. vcftools报错:Writing PLINK PED and MAP files ... Error: Could not open temporary file.解决方案

    一般来说有两种解决方案. 第一种:添加“--plink-tped”参数: 用vcftools的“--plink”参数生成plink格式文件时,小样本量测试可以正常生成plink格式,用大样本量时产生W ...

  8. Java:concurrent包下面的Map接口框架图(ConcurrentMap接口、ConcurrentHashMap实现类)

    Java集合大致可分为Set.List和Map三种体系,其中Set代表无序.不可重复的集合:List代表有序.重复的集合:而Map则代表具有映射关系的集合.Java 5之后,增加了Queue体系集合, ...

  9. 【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 ...

  10. 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 ...

随机推荐

  1. Qt编写视频监控系统74-悬浮工具栏(半透明/上下左右位置/自定义按钮)

    一.前言 在监控系统中一般在视频实时预览的时候,希望提供一个悬浮工具条,可以显示一些提示信息比如分辨率.码率.帧率,提供一堆快捷操作按钮,可以录像.抓拍.云台控制.关闭等操作,参考了国内很多监控厂商客 ...

  2. Qt通用方法及类库10

    函数名 //获取保存的文件 static QString getSaveName(const QString &filter, QString defaultDir = QCoreApplic ...

  3. Qt编写地图综合应用20-多浏览器内核

    一.前言 本人写Qt程序这么多年,比较喜欢支持多个Qt版本,尤其是钟情于支持任意Qt版本+任意系统+任意编译器,这句话说起来简单其实实现起来就不容易了,首先你得有个很多版本的测试环境,起码十几个Qt环 ...

  4. 即时通讯技术文集(第36期):《跟着源码学IM》系列专题 [共12篇]

    为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第36 期. [-1-] 跟着源码学IM(一):手把手教你用Netty实现心跳机制.断线重连机制 ...

  5. 开源即时通讯IM框架MobileIMSDK的微信小程序端开发快速入门

    一.理论知识准备 您需要对微信小程序开发有所了解: 1)真正零基础入门学习笔记系列 2)从零开始的微信小程序入门教程 3)最全教程:微信小程序开发入门详解 您需要对WebSocket技术有所了解: 1 ...

  6. Hugo 静态博客部署

    I. 前提条件 1.1 安装 Hugo 1.1.1 Windows 1.下载 Hugo(建议下载扩展版):Hugo(github.com) 2.解压 Hugo 压缩包到指定目录. 3.[Win + R ...

  7. spark (六) RDD算子(operator)

    目录 1 转换算子(transformer)(将旧的RDD包装成新RDD) 1.1 单值类型 1.1.1 map 1.1.2 mapPartition 1.1.3 mapPartitionsWithI ...

  8. w3cschool-Apache Kafka 教程

    参考https://www.w3cschool.cn/apache_kafka/ Apache Kafka 基础 2021-07-27 16:23 更新 对于大数据,我们要考虑的问题有很多,首先海量数 ...

  9. Superset用户集成方案2

    superset 认证分析 superset基于flask-appbuilder开发,security基于flask_appbuilder.security,翻阅其代码, 找到入口: superset ...

  10. 二叉树神级遍历算法:morris遍历算法

    morris遍历的实质 建立一种机制,对于没有左子树的节点只到达一次,对于有左子树的节点会到达两次 morris遍历的实现原则 记作当前节点为cur. 如果cur无左孩子,cur向右移动(cur=cu ...