-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmap.go
More file actions
142 lines (117 loc) · 2.94 KB
/
Copy pathmap.go
File metadata and controls
142 lines (117 loc) · 2.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package main
import (
"sync"
)
// ========== 解法一:sync.RWMutex 并发安全 Map ==========
// RWMutexMap 使用读写锁 RWMutex 保护 map,适合读多写少场景。
// 多个 goroutine 可以同时持有读锁,写锁独占。
type RWMutexMap struct {
mu sync.RWMutex
data map[string]int
}
func NewRWMutexMap() *RWMutexMap {
return &RWMutexMap{data: make(map[string]int)}
}
func (m *RWMutexMap) Get(key string) (int, bool) {
m.mu.RLock()
defer m.mu.RUnlock()
v, ok := m.data[key]
return v, ok
}
func (m *RWMutexMap) Set(key string, val int) {
m.mu.Lock()
defer m.mu.Unlock()
m.data[key] = val
}
func (m *RWMutexMap) Delete(key string) {
m.mu.Lock()
defer m.mu.Unlock()
delete(m.data, key)
}
func (m *RWMutexMap) Len() int {
m.mu.RLock()
defer m.mu.RUnlock()
return len(m.data)
}
// ========== 解法二:sync.Map 类型安全封装 ==========
// SyncMapWrapper 封装标准库 sync.Map,提供类型安全的 Get/Set/Delete 接口。
// sync.Map 适合:读多写少、key 集合稳定(写入一次读取多次)、
// 各 goroutine 操作的 key 集合基本不相交。
type SyncMapWrapper struct {
m sync.Map
}
func NewSyncMapWrapper() *SyncMapWrapper {
return &SyncMapWrapper{}
}
func (sm *SyncMapWrapper) Get(key string) (int, bool) {
v, ok := sm.m.Load(key)
if !ok {
return 0, false
}
return v.(int), true
}
func (sm *SyncMapWrapper) Set(key string, val int) {
sm.m.Store(key, val)
}
func (sm *SyncMapWrapper) Delete(key string) {
sm.m.Delete(key)
}
// ========== 解法三:分段锁 ShardMap(高并发利器)==========
const numShards = 32
type shard struct {
mu sync.RWMutex
data map[string]int
}
// ShardMap 使用分段锁策略,将一个大 map 拆分为 32 个 shard。
// 每个 shard 有独立的 RWMutex,key 通过 FNV-1a 哈希路由到对应 shard。
// 锁粒度降低 32 倍,大大减少竞争,适合超高并发写入场景。
type ShardMap struct {
shards [numShards]*shard
}
func NewShardMap() *ShardMap {
sm := &ShardMap{}
for i := 0; i < numShards; i++ {
sm.shards[i] = &shard{data: make(map[string]int)}
}
return sm
}
// fnv32 计算 key 的 FNV-1a 哈希值
func fnv32(key string) uint32 {
h := uint32(2166136261)
for i := 0; i < len(key); i++ {
h ^= uint32(key[i])
h *= 16777619
}
return h
}
func (sm *ShardMap) getShard(key string) *shard {
return sm.shards[fnv32(key)%numShards]
}
func (sm *ShardMap) Get(key string) (int, bool) {
sh := sm.getShard(key)
sh.mu.RLock()
defer sh.mu.RUnlock()
v, ok := sh.data[key]
return v, ok
}
func (sm *ShardMap) Set(key string, val int) {
sh := sm.getShard(key)
sh.mu.Lock()
defer sh.mu.Unlock()
sh.data[key] = val
}
func (sm *ShardMap) Delete(key string) {
sh := sm.getShard(key)
sh.mu.Lock()
defer sh.mu.Unlock()
delete(sh.data, key)
}
func (sm *ShardMap) Len() int {
total := 0
for i := 0; i < numShards; i++ {
sm.shards[i].mu.RLock()
total += len(sm.shards[i].data)
sm.shards[i].mu.RUnlock()
}
return total
}