Skip to content

MAP

键值对关联数组

  • map集合使用前一定先要make
  • map 键值对是无序的
  • map key值是不重复的
go
//方式1:通过make定义
var map1 map[int]string = make(map[int]string, 10)
map1[1] = "张三"
map1[2] = "王五"
fmt.Println(map1)

//方式2:通过make定义 不指定长度
var map2 map[int]string = make(map[int]string)
map2[1] = "张三"
fmt.Println(map2)

//方式3: 键值对初始化
map3 := map[int]string{
    1: "张三",
    2: "王五",
}
fmt.Println(map3)

常规操作

go
//增删改
var map4 map[int]string = make(map[int]string)
map4[3] = "王五"  //增加
map4[3] = "李四"  //修改
delete(map4, 3) //删除
fmt.Println(map4)

//遍历1
for i := 0; i < len(map4); i++ {
    fmt.Println(map4[i])
}
//遍历2
for key, value := range map4 {
    fmt.Println(key, value)
}

并发锁

互斥锁

  • 基于sync.Mutex执行的互斥锁
  • 适用于读写不确定场景,即读写次数没有明显的区别的场景。

读写锁

  • 基于sync.RWMutex执行的读写锁
  • 适用于读多写少的场景。

sync.map

  • go自带的map锁,底层通分离读写map和原子指令来实现读的近似无锁,并通过延迟更新的方式来保证读的无锁化。
  • 读多修改少,元素增加删除频率不高的情况

分片锁

  • 基于读写锁再次优化。将这个 map 分成 n 块,每个块之间的读写操作都互不干扰,从而降低冲突的可能性。
  • 常使用高并发场景。减少锁的竞争。
go
package main

import (
	"fmt"
	"github.com/zeromicro/go-zero/core/hash"
	"sync"
	"time"
)

// 代表互斥锁
type MutexMap struct {
	sync.Mutex
	m map[string]int
}

// 代表读写锁
type RWMutexMap struct {
	sync.RWMutex
	m map[string]int
}

// 分片锁
const N = 32

type SafeMap struct {
	locks [N]sync.RWMutex
	maps  [N]map[string]int
}

var mutexMap *MutexMap
var rwMutexMap *RWMutexMap
var syncMap *sync.Map

func main() {
	mutexMap = &MutexMap{m: make(map[string]int, 100)}
	rwMutexMap = &RWMutexMap{m: make(map[string]int, 100)}
	syncMap = &sync.Map{}

	sm := &SafeMap{}
	for i := 0; i < N; i++ {
		sm.maps[i] = make(map[string]int)
	}

	//互斥锁
	for i := 0; i < 10; i++ {
		go func() {
			mutexMap.Lock()
			mutexMap.m["a"] = i
			mutexMap.Unlock()
			fmt.Printf("%+v \r\n", mutexMap)
		}()
	}
	time.Sleep(1 * time.Second)
	fmt.Printf("最终: %+v \r\n", mutexMap)

	//读写锁
	for i := 0; i < 10; i++ {
		go func() {
			rwMutexMap.Lock()
			rwMutexMap.m["b"] = i
			rwMutexMap.Unlock()
			fmt.Printf("%+v \r\n", rwMutexMap)
		}()
	}
	time.Sleep(1 * time.Second)
	fmt.Printf("最终: %+v \r\n", rwMutexMap)

	//sync.map
	for i := 0; i < 10; i++ {
		go func() {
			syncMap.Store("c", i)
			fmt.Printf("%+v \r\n", syncMap)
		}()
	}
	time.Sleep(1 * time.Second)
	fmt.Printf("最终: %+v \r\n", syncMap)

	//分片锁
	key := "key"
	index := hash.Hash([]byte(key)) % N
	sm.locks[index].RLock()
	value := sm.maps[index][key]
	sm.locks[index].RUnlock()

	fmt.Printf("最终: %+v \r\n", value)
}