// 對(duì)外暴露的map
type MutexMap struct {
items map[string]interface{} // 為了和上面的ConcurrentMap做比較,都采用string->interface的方式
mu *sync.RWMutex // 讀寫(xiě)鎖
}
// 新建一個(gè)map
func NewMutexMap() *MutexMap {
return &MutexMap{
items: map[string]interface{}{},
mu: new(sync.RWMutex),
}
}
// Set 設(shè)置key,value
func (m MutexMap) Set(key string, value interface{}) {
m.mu.Lock() // 加鎖(全鎖定)
m.items[key] = value // 賦值
m.mu.Unlock() // 解鎖
}
// Get 獲取key對(duì)應(yīng)的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 統(tǒng)計(jì)key個(gè)數(shù)
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性能對(duì)比
package main
import (
"math/rand"
"strconv"
"sync"
"testing"
)
// 10萬(wàn)次的賦值,10萬(wàn)次的讀取
var times int = 100000
// 測(cè)試ConcurrentMap
func BenchmarkTestConcurrentMap(b *testing.B) {
for k := 0; k < b.N; k++ {
b.StopTimer()
// 產(chǎn)生10000個(gè)不重復(fù)的鍵值對(duì)(string -> int)
testKV := map[string]int{}
for i := 0; i < 10000; i++ {
testKV[strconv.Itoa(i)] = i
}
// 新建一個(gè)ConcurrentMap
pMap := NewConcurrentMap()
// set到map中
for k, v := range testKV {
pMap.Set(k, v)
}
// 開(kāi)始計(jì)時(shí)
b.StartTimer()
wg := sync.WaitGroup{}
wg.Add(2)
// 賦值
go func() {
// 對(duì)隨機(jī)key,賦值times次
for i := 0; i < times; i++ {
index := rand.Intn(times)
pMap.Set(strconv.Itoa(index), index+1)
}
wg.Done()
}()
// 讀取
go func() {
// 對(duì)隨機(jī)key,讀取times次
for i := 0; i < times; i++ {
index := rand.Intn(times)
pMap.Get(strconv.Itoa(index))
}
wg.Done()
}()
// 等待兩個(gè)協(xié)程處理完畢
wg.Wait()
}
}
// 測(cè)試map加鎖
func BenchmarkTestMap(b *testing.B) {
for k := 0; k < b.N; k++ {
b.StopTimer()
// 產(chǎn)生10000個(gè)不重復(fù)的鍵值對(duì)(string -> int)
testKV := map[string]int{}
for i := 0; i < 10000; i++ {
testKV[strconv.Itoa(i)] = i
}
// 新建一個(gè)MutexMap
pMap := NewMutexMap()
// set到map中
for k, v := range testKV {
pMap.Set(k, v)
}
// 開(kāi)始計(jì)時(shí)
b.StartTimer()
wg := sync.WaitGroup{}
wg.Add(2)
// 賦值
go func() {
// 對(duì)隨機(jī)key,賦值100萬(wàn)次
for i := 0; i < times; i++ {
index := rand.Intn(times)
pMap.Set(strconv.Itoa(index), index+1)
}
wg.Done()
}()
// 讀取
go func() {
// 對(duì)隨機(jī)key,讀取100萬(wàn)次
for i := 0; i < times; i++ {
index := rand.Intn(times)
pMap.Get(strconv.Itoa(index))
}
wg.Done()
}()
// 等待兩個(gè)協(xié)程處理完畢
wg.Wait()
}
}
// 測(cè)試sync.map
func BenchmarkTestSyncMap(b *testing.B) {
for k := 0; k < b.N; k++ {
b.StopTimer()
// 產(chǎn)生10000個(gè)不重復(fù)的鍵值對(duì)(string -> int)
testKV := map[string]int{}
for i := 0; i < 10000; i++ {
testKV[strconv.Itoa(i)] = i
}
// 新建一個(gè)sync.Map
pMap := &sync.Map{}
// set到map中
for k, v := range testKV {
pMap.Store(k, v)
}
// 開(kāi)始計(jì)時(shí)
b.StartTimer()
wg := sync.WaitGroup{}
wg.Add(2)
// 賦值
go func() {
// 對(duì)隨機(jī)key,賦值10萬(wàn)次
for i := 0; i < times; i++ {
index := rand.Intn(times)
pMap.Store(strconv.Itoa(index), index+1)
}
wg.Done()
}()
// 讀取
go func() {
// 對(duì)隨機(jī)key,讀取10萬(wàn)次
for i := 0; i < times; i++ {
index := rand.Intn(times)
pMap.Load(strconv.Itoa(index))
}
wg.Done()
}()
// 等待兩個(gè)協(xié)程處理完畢
wg.Wait()
}
}
執(zhí)行命令:go test -bench=.

image.png