• sync.Map与Concurrent Map


    1. sync.Map

    1.1. map并发不安全

    go1.6以后map有了并发的安全检查,所以如果在并发环境中读写map就会报错

    func unsafeMap()  {
        // 创建一个map对象
    	m := make(map[int]int)
    	go func() {
    		for {
                // 尝试读取数据
    			_ = m[1]
    		}
    	}()
    	go func() {
    		for {
                // 尝试写入数据
    			m[2] = 2
    		}
    	}()
        // 阻塞
    	select {}
    }
    
    // output
    // fatalerror: concurrent map read and map write

    1.2 安全map

     并发环境下面使用安全的map

    1.2.1 自定义结构体

    // 通过内嵌读写锁的方式,保证我们使用map的安全性
    type MyMap struct{
    	sync.RWMutex
        m map[string]int  // 需要一个并发的map[string]int类型
    }
    
    // 封装一个创建map对象的方法
    func NewMyMap()*MyMap{
        smp:=new(MyMap)
        smp.m = make(map[string]int)
        return smp
    } 

    注意:我们定义使用什么类型的map,那么就内置什么类型的map 

    1.2.2 sync.Map

    go1.9以后sync包中加入了安全的map对象,,syn.Map不支持普通的map操作,需要使用sync.Map提供的api使用

      • 创建sync.Map对象

        //1. 不需要通过map的方式进行创建,通过声明的方式或者new创建即可
        var smap sync.Map
        
        //2. 通过new的方式创建
        smap:=new(sync.Map)
      • sync.Map 存储数据store方法

        //func (m *Map) Store(key, value interface{})
        // key,value 都是接口类型,可以存储任何类型的数据
        smap.Store(1,"MrSun") 
      • sync.Map读取数据

        // func (m *Map) Load(key interface{}) (value interface{}, ok bool)
        // key: 键,value: 如果数据存在则返回对应的值,不存在则返回nil,ok: 表示值知否被找到
        // 记得对数据断言处理
        val,ok:=smap.Load(1)
      • sync.Map,存在则读取,不存在存储

        // func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool)
        // key,value: 要存储的key与value
        //actual: 如果存在则返回存在的值,如果不存在则存储并返回存储的值
        // laoded: 如果数据存在,则true,如果数据不存在则false
        actual, loaded := smap.LoadOrStore(1, "MrSun")
      • sync.Map 遍历

        // 创建map
        smap:=new(sync.Map)
        smap.LoadOrStore(1, "MrSun")
        smap.LoadOrStore(2, "hello")
        smap.LoadOrStore(3, "golang")
        smap.LoadOrStore(4, "bilili")
        //func (m *Map) Range(f func(key, value interface{}) bool)
        // 用户处理数据的回调函数,回调函数的参数是key,value,返回值是bool
        smap.Range(func(key, value interface{}) bool {
        		smap.Store(5,"heihei")
        		fmt.Println(key,value)
        		return true
        }) 

        // 注意:Range方法遍历的是map的副本
    • sync.Map 数据删除
    • // func (m *Map) Delete(key interface{})
      // key: 要删除数据的key值
      smap.Delete(1)
      

    1.2.3 sync.Map与内置读写锁性能对比

    • 4核心以前内置的读写锁map性能要高

    • 4核心后,sync.Map 性能要高

    • sync.Map 性能稳定

    1.2.4 sync.Map使用场景

    The Map type is optimized for two common use cases:

    1. when the entry for a given key is only ever written once but read many times, as in caches that only grow.

    2. when multiple goroutines read, write, and overwrite entries for disjoint sets of keys. In these two cases, use of a Map may significantly reduce lock contention compared to a Go map paired with a separate Mutex or RWMutex.

    • 写少读多的情况

    • 多goroutine,读、写、复写 不同数据的情况 【没遇到过】

    • 多核心情况使用

    建议:没有特别要求的情况,两者都可以,go1.9以后建议直接使用sync.Map

     

    1.2.5 sync.Map源码剖析

    sync.Map

    2. Concurrent Map

    并发安全map,类似java下面的java.util.ConcurrentHashMap,适合读写都相对比较频繁的情况

    2.1 基本原理

    采用分段锁机制,从而提高并发安全的性能

    2.2 concurrent map下载

    # github 星标 最高的一个
    go get "github.com/orcaman/concurrent-map"

    2.2 基本使用

    不同的第三方包模块使用API都不一样,使用那个模块需要查看对应模块的文档

    import "github.com/orcaman/concurrent-map"
    
    func concurrentMap()  {
    	mp:=cmap.New()
    	// 存储值,key只能是string类型,value可以是任意类型
    	mp.Set("1","hello")
    	mp.Set("2","golang")
        //val: 如果存在则返回值,不存在则返回nil
        // ok: 表示值如果存在则是true,如果不存在则是false
    	val,ok:=mp.Get("2")
    	if ok{
    		fmt.Println(val.(string))
    	}
    	mp.Remove("1")
    	_,ok=mp.Get("1")
    	if !ok{
    		fmt.Println("data is not exist")
    	}
    }
  • 相关阅读:
    R-CNN算法中NMS的具体做法
    Spring之Environment
    Spring之Aware
    每晚夜里自我独行,随处荡,多冰冷,以往为了自我挣扎
    Java 反射机制
    Java string String
    Java int Integer
    Java final
    Java toString()方法
    Java Enum
  • 原文地址:https://www.cnblogs.com/lurenq/p/11940994.html
Copyright © 2020-2023  润新知