并发环境应用map的解决方案

赵嬷嬷
• 阅读 2247

众所周知,golang的map是非协程安全的(go1.6版本以后,go1.6之前读安全),而并发读写map的需求应该是很普遍的。举例如下:

package main

import "fmt"

func main() {
    a := make(map[int]bool, 0)

    for i:=0;i<100;i++{
        go func() {
            for i := 0; i < 20000; i++ {
                a[i] = false
                fmt.Printf("%v %v\n",i,a[i])
            }

        }()
    }
}

运行报错:
fatal error: concurrent map writes
1.9版本之前,官方提供的解决方案是自己封装个带同步锁的struct。例如:

package main

import (
    "fmt"
    "sync"

)

type SafeMap struct{
    sync.RWMutex
    data map[int]int
}

func main() {
    a := SafeMap{data: make(map[int]int)}
    for i:=0;i<100;i++{
        go func() {
            for j := 0; j < 20000; j++ {
                a.Lock()
                a.data[j] = i
                fmt.Printf("%v %v\n", i, j)
                a.Unlock()
            }
        }()
    }
}

1.9版本以后,sync包引入了sync.Map,性能比起之前的解决方案有比较大的提升:

package main

    import (
        "fmt"
        "sync"
    )
    
    func main() {
        a := new(sync.Map)
        wg := new(sync.WaitGroup)
        wg.Add(100)
        for i:=0;i<100;i++{
            go func() {
                for j := 0; j < 100; j++ {
                    a.Store(i, j)
                }
                wg.Done()
            }()
        }
        wg.Wait()
        a.Range(func(key, value interface{}) bool {
            fmt.Printf("%v %v\n", key, value)
    
            return true
        })
    }

点赞
收藏
评论区
推荐文章
郜小超 郜小超
4年前
js二维数组重新转化 Echarts中遇到的数据问题
后台返回的数据需要重新整合vararr1,1,1,2,2,2,3,3,3,4,4,4,5,5,5varnewArrayarr0.map(function(col,i)returnarr.map(function(row)returnrowi;));
Easter79 Easter79
3年前
typescript中继承Map、Set报错的解决
Map、Set的polyfill实现是可以继承的if(!this.Map){//polyfill}else{(function(){//可继承Map替代原生MapvarGMapglobalThis.Map;try{Map.call({});}catch
东方客主 东方客主
4年前
go-map源码简单分析(map遍历为什么时随机的)
GO中map的底层是如何实现的首先Go语言采用的是哈希查找表,并且使用链表解决哈希冲突。GO的内存模型先看这一张map原理图(https://imghelloworld.osscnbeijing.aliyuncs.com/49dfa7b81e19fbab143ddc0a7b3b7fa0.png)map再来看
Wesley13 Wesley13
3年前
java8新特性
Stream将List转换为Map,使用Collectors.toMap方法进行转换背景:User类,类中分别有id,name,age三个属性。List集合,userList,存储User对象1、指定keyvalue,value是对象中的某个属性值。 Map<Integer,StringuserMap1userList.str
happlyfox happlyfox
4年前
[concurrent-map]-并发map在go中的使用
关于我通过学习和分享的过程,将自己工作中的问题和技术总结输出,希望菜鸟和老鸟都能通过自己的文章收获新的知识,并付诸实施。引言Go语言原生的map类型并不支持并发读写。在Go1.9之前,go语言标准库中并没有实现并发map。在Go1.9中,引入了sync.Map。concurrentmap的优势concurrentm
BichonCode BichonCode
4年前
Java的其他Map
一、LinkedHashMap1.1应用场景HashMap是无序的,当我们希望有顺序地去存储keyvalue时,就需要使用LinkedHashMap了。1.2插入顺序和访问顺序LinkedHashMap默认的构造参数是默认 插入顺序的,就是说你插入的是什么顺序,读出来的就是什么顺序,但是也有访问顺序,就是说你访问了一个key,这个
Bill78 Bill78
4年前
Python的map()方法如何使用?
在学习map()方法之前,我们先在交互模式下看下map()的用法说明。(https://imghelloworld.osscnbeijing.aliyuncs.com/5c398969745b516276e1f7f5c7dcb764.png)从上面可以得到的信息是:map()返回的是一个map对象(python2.0中返回的是列表
Stella981 Stella981
3年前
HashMap 初始化时赋值
一般初始化一个map并且给map赋值的写法:HashMap<String,StringmapnewHashMap<String,String();map.put("name","test");map.put("age","20");但是我想在初始化的时候就直接给map中set值。
Wesley13 Wesley13
3年前
Java(20~24)
1、Collection中的集合称为单列集合,Map中的集合称为双列集合(键值对集合)。!(https://oscimg.oschina.net/oscnet/adbdd980af28370d467fc2170913eecc89e.png)2、Map常用方法:map.put()  map.get()  map.remove()  map.k
Wesley13 Wesley13
3年前
Java ConcurrentHashMap存入引用对象时也是线程安全的
本人小白,看到资料说ConcurrentHashMap是线程安全的,get过程不需要加锁,put是线程安全的,推荐高并发时使用.但是本人不清楚是否该map中存入的引用类型对象,对象属性变化也是否线程安全的,看了很多资料,貌似都没说明这一点,所以写代码测试一下,packagetestConcurrentHashMap;importjava.util
IT全栈视野 IT全栈视野
11个月前
在 Go 语言中,实现缓存的多种方式
第1种,使用sync.Map代码示例packagemainimport("fmt""sync""time")funcmain()varcachesync.Map//存储数据到缓存cache.Store("key1","value1")cache.Store