// 对外暴露的map
type MutexMap struct {
items map[string]interface{} // 为了和上面的ConcurrentMap做比较,都采用string->interface的方式
mu *sync.RWMutex // 读写锁
}
// 新建一个map
func NewMutexMap() *MutexMap {
return &MutexMap{
items: map[string]interface{}{},
mu: new(sync.RWMutex),
}
}
// Set 设置key,value
func (m MutexMap) Set(key string, value interface{}) {
m.mu.Lock() // 加锁(全锁定)
m.items[key] = value // 赋值
m.mu.Unlock() // 解锁
}
// Get 获取key对应的value
func (m MutexMap) Get(key string) (value interface{}, ok bool) {
m.mu.RLock() // 加锁(读锁定)
value, ok = m.items[key] // 取值
m.mu.RUnlock() // 解锁
return value, ok
}
// Count 统计key个数
func (m MutexMap) Count() int {
m.mu.RLock() // 加锁(读锁定)
count := len(m.items)
m.mu.RUnlock() // 解锁
return count
}
// Keys 所有的key
func (m MutexMap) Keys() []string {
m.mu.RLock() // 加锁(读锁定)
keys := make([]string, len(m.items))
for k := range m.items {
keys = append(keys, k)
}
m.mu.RUnlock() // 解锁
return keys
}
sync.map 、MutexMap 、ConcurrentMap性能对比
package main
import (
"math/rand"
"strconv"
"sync"
"testing"
)
// 10万次的赋值,10万次的读取
var times int = 100000
// 测试ConcurrentMap
func BenchmarkTestConcurrentMap(b *testing.B) {
for k := 0; k < b.N; k++ {
b.StopTimer()
// 产生10000个不重复的键值对(string -> int)
testKV := map[string]int{}
for i := 0; i < 10000; i++ {
testKV[strconv.Itoa(i)] = i
}
// 新建一个ConcurrentMap
pMap := NewConcurrentMap()
// set到map中
for k, v := range testKV {
pMap.Set(k, v)
}
// 开始计时
b.StartTimer()
wg := sync.WaitGroup{}
wg.Add(2)
// 赋值
go func() {
// 对随机key,赋值times次
for i := 0; i < times; i++ {
index := rand.Intn(times)
pMap.Set(strconv.Itoa(index), index+1)
}
wg.Done()
}()
// 读取
go func() {
// 对随机key,读取times次
for i := 0; i < times; i++ {
index := rand.Intn(times)
pMap.Get(strconv.Itoa(index))
}
wg.Done()
}()
// 等待两个协程处理完毕
wg.Wait()
}
}
// 测试map加锁
func BenchmarkTestMap(b *testing.B) {
for k := 0; k < b.N; k++ {
b.StopTimer()
// 产生10000个不重复的键值对(string -> int)
testKV := map[string]int{}
for i := 0; i < 10000; i++ {
testKV[strconv.Itoa(i)] = i
}
// 新建一个MutexMap
pMap := NewMutexMap()
// set到map中
for k, v := range testKV {
pMap.Set(k, v)
}
// 开始计时
b.StartTimer()
wg := sync.WaitGroup{}
wg.Add(2)
// 赋值
go func() {
// 对随机key,赋值100万次
for i := 0; i < times; i++ {
index := rand.Intn(times)
pMap.Set(strconv.Itoa(index), index+1)
}
wg.Done()
}()
// 读取
go func() {
// 对随机key,读取100万次
for i := 0; i < times; i++ {
index := rand.Intn(times)
pMap.Get(strconv.Itoa(index))
}
wg.Done()
}()
// 等待两个协程处理完毕
wg.Wait()
}
}
// 测试sync.map
func BenchmarkTestSyncMap(b *testing.B) {
for k := 0; k < b.N; k++ {
b.StopTimer()
// 产生10000个不重复的键值对(string -> int)
testKV := map[string]int{}
for i := 0; i < 10000; i++ {
testKV[strconv.Itoa(i)] = i
}
// 新建一个sync.Map
pMap := &sync.Map{}
// set到map中
for k, v := range testKV {
pMap.Store(k, v)
}
// 开始计时
b.StartTimer()
wg := sync.WaitGroup{}
wg.Add(2)
// 赋值
go func() {
// 对随机key,赋值10万次
for i := 0; i < times; i++ {
index := rand.Intn(times)
pMap.Store(strconv.Itoa(index), index+1)
}
wg.Done()
}()
// 读取
go func() {
// 对随机key,读取10万次
for i := 0; i < times; i++ {
index := rand.Intn(times)
pMap.Load(strconv.Itoa(index))
}
wg.Done()
}()
// 等待两个协程处理完毕
wg.Wait()
}
}
执行命令:go test -bench=.
image.png