// 對外暴露的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 設(shè)置key,value
func (m MutexMap) Set(key string, value interface{}) {
m.mu.Lock() // 加鎖(全鎖定)
m.items[key] = value // 賦值
m.mu.Unlock() // 解鎖
}
// Get 獲取key對應(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)計key個數(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性能對比
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()
// 產(chǎn)生10000個不重復(fù)的鍵值對(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()
}()
// 等待兩個協(xié)程處理完畢
wg.Wait()
}
}
// 測試map加鎖
func BenchmarkTestMap(b *testing.B) {
for k := 0; k < b.N; k++ {
b.StopTimer()
// 產(chǎn)生10000個不重復(fù)的鍵值對(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()
}()
// 等待兩個協(xié)程處理完畢
wg.Wait()
}
}
// 測試sync.map
func BenchmarkTestSyncMap(b *testing.B) {
for k := 0; k < b.N; k++ {
b.StopTimer()
// 產(chǎn)生10000個不重復(fù)的鍵值對(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()
}()
// 等待兩個協(xié)程處理完畢
wg.Wait()
}
}
執(zhí)行命令:go test -bench=.
image.png