concurrent map使用
目录
- 概述
- 例子
1. 概述
- Go语言原生的map类型并不支持并发读写。concurrent-map提供了一种高性能的解决方案:通过对内部map进行分片,降低锁粒度,从而达到最少的锁等待时间(锁冲突)
- 在Go 1.9之前,go语言标准库中并没有实现并发map。在Go 1.9中,引入了sync.Map。新的sync.Map与此concurrent-map有几个关键区别。
- 标准库中的sync.Map是专为append-only场景设计的。因此,如果想将Map用于一个类似内存数据库,那么使用concurrent-map可能会更受益。
- sync.Map在读多写少性能比较好,否则并发性能很差
2. 例子
- 引用:
go test "github.com/orcaman/concurrent-map"
- 例子使用了部分方法,具体查看:concurrent_map_test.go
package main
import (
"encoding/json"
"fmt"
cmap "github.com/orcaman/concurrent-map"
"github.com/prometheus/common/log"
"strconv"
)
type Animal struct {
name string
}
func main() {
m := cmap.New()
elephant := Animal{"elephant"}
monkey := Animal{"monkey"}
m.Set("elephant", elephant)
m.Set("monkey", monkey)
tmp, ok := m.Get("elephant")
if ok == false {
log.Error("ok should be true for item stored within the map.")
}
elephant, ok = tmp.(Animal)
if !ok {
log.Error("expecting an element, not null.")
}
if elephant.name != "elephant" {
log.Error("item was modified.")
}
if m.Has("elephant") == false {
log.Error("element exists, expecting Has to return True.")
}
m.Remove("monkey")
if m.Count() != 0 {
log.Error("Expecting count to be zero once item was removed.")
}
monkey = Animal{"monkey"}
m.Set("monkey", monkey)
v, exists := m.Pop("monkey")
if !exists {
log.Error("Pop didn't find a monkey.")
}
m1, ok := v.(Animal)
if !ok || m1 != monkey {
log.Error("Pop found something else, but monkey.")
}
if m.Count() != 100 {
log.Error("Expecting 100 element within map.")
}
if m.IsEmpty() == false {
log.Error("new map should be empty")
}
for i := 0; i < 100; i++ {
m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
}
counter := 0
for item := range m.IterBuffered() {
println(item.Val)
val := item.Val
name := item.Val.(Animal).name
fmt.Println(name)
if val == nil {
log.Error("Expecting an object.")
}
counter++
}
m.Clear()
for i := 0; i < 100; i++ {
m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
}
m.IterCb(func(key string, v interface{}) {
num, ok := v.(Animal)
fmt.Println(key,"---",num.name)
if !ok {
log.Error("Expecting an animal object")
}
counter++
})
items := m.Items()
if len(items) != 100 {
log.Error("We should have counted 100 elements.")
}
m.Clear()
m.Set("a", 1)
m.Set("b", 2)
j, err := json.Marshal(m)
if err != nil {
log.Error(err)
}
fmt.Println(j)
keys := m.Keys()
println(keys)
animals := map[string]interface{}{
"elephant": Animal{"elephant"},
"monkey": Animal{"monkey"},
}
m.MSet(animals)
println(m.Count())
dolphin := Animal{"dolphin"}
whale := Animal{"whale"}
tiger := Animal{"tiger"}
lion := Animal{"lion"}
cb := func(exists bool, valueInMap interface{}, newValue interface{}) interface{} {
nv := newValue.(Animal)
if !exists {
return []Animal{nv}
}
res := valueInMap.([]Animal)
return append(res, nv)
}
m.Set("marine", []Animal{dolphin})
m.Upsert("marine", whale, cb)
m.Upsert("predator", tiger, cb)
m.Upsert("predator", lion, cb)
}