SyncMap:源码解读

本文深入探讨了Go内建的Map的特性及常见错误,如未初始化和并发读写问题。接着介绍了实现并发安全Map的两种方式:直接加读写锁和分片加锁,分析了各自的优缺点。特别地,详细解读了`sync.Map`的源码,包括其工作流程和优化策略,指出其适用于新增一次读取很多次的场景。最后总结了`sync.Map`的空间换时间策略、double-check机制和延迟删除特点。
摘要由CSDN通过智能技术生成

线程安全的Map

Go内建的Map

Go内建的Map类型:Map[K]V
K必须是可比较类型,V可以是任意类型也可以是nil
在Go中整数、浮点数、复数、string、chan、指针、接口、包含可比较元素的struct和数组都是可比较类型,slice、map、func不是可比较类型

注意:使用包含可比较元素的struct当做key时,如果struct的可比较元素值改变了那么无法根据这个struct获取到对应的value

import "fmt"

type structKey struct {
	a int32
}

func testStructKey() {
	var key structKey
	key.a = 1
	m := make(map[structKey]string)
	m[key] = "hello"
	fmt.Printf("init value is :%v\n", m[key])
	key.a = 2
	fmt.Printf("key change value is: %v\n", m[key])
}

在Go中,map[K]可以返回一个值也可以返回两个值,因为当K不存在时会返回零值,但这个零值是本身就设置的零值还是由于K不存在返回的,就需要根据第二个返回值判断,第二个返回值是False说明是因为K不存在,第二个返回值是True说明K存在是本身设置的零值

Map是无序的,当遍历一个Map的时候,迭代元素的顺序不确定
如果想要保证元素有序,比如按照插入顺序排序,那么可以使用orderedMap
orderedMap: https://github.com/elliotchance/orderedmap

Map常见错误

未初始化

Map在使用前一定要初始化
未初始化的Map直接赋值会导致panic,取值不会panic会取到零值

并发读写

Go内建的Map不是并发安全的,Go的runtime会检测Map是否存在并发读写,如果存在那么会panic

实现并发安全的Map

直接加读写锁
源码实现
type RWMutexMap struct {
	rMu sync.RWMutex
	m   map[interface{}]interface{}
}

func (m *RWMutexMap) Store(key interface{}, value interface{}) {
	m.rMu.Lock()
	defer m.rMu.Unlock()
	m.m[key] = value
}

func (m *RWMutexMap) Load(key interface{}) (interface{}, bool) {
	m.rMu.RLock()
	defer m.rMu.RUnlock()
	value, ok := m.m[key]
	return value, ok
}

func (m *RWMutexMap) Delete(key interface{}) {
	m.rMu.Lock()
	defer m.rMu.Unlock()
	delete(m.m, key)
}

func (m *RWMutexMap) Len() int {
	m.rMu.RLock()
	defer m.rMu.RUnlock()
	return len(m.m)
}

func (m *RWMutexMap) Each(f func(key interface{}, value interface{}) error) error {
	m.rMu.RLock()
	defer m.rMu.RUnlock()
	for key, value := range m.m {
		err := f(key, value)
		if err 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值