gmap

并发安全Map,最常用的并发安全数据结构。

使用场景

需要并发安全支持的map数据类型场景。例如,map对象会被多个goroutine读写时。

使用方式

  1. import "gitee.com/johng/gf/g/container/gmap"

方法列表godoc.org/github.com/johng-cn/gf/g/container/gmap

  1. type IntBoolMap
  2. func NewIntBoolMap(safe ...bool) *IntBoolMap
  3. func (this *IntBoolMap) BatchRemove(keys []int)
  4. func (this *IntBoolMap) BatchSet(m map[int]bool)
  5. func (this *IntBoolMap) Clear()
  6. func (this *IntBoolMap) Clone() map[int]bool
  7. func (this *IntBoolMap) Contains(key int) bool
  8. func (this *IntBoolMap) Get(key int) bool
  9. func (this *IntBoolMap) GetOrSet(key int, value bool) bool
  10. func (this *IntBoolMap) GetOrSetFunc(key int, f func() bool) bool
  11. func (this *IntBoolMap) GetOrSetFuncLock(key int, f func() bool) bool
  12. func (this *IntBoolMap) IsEmpty() bool
  13. func (this *IntBoolMap) Iterator(f func(k int, v bool) bool)
  14. func (this *IntBoolMap) Keys() []int
  15. func (this *IntBoolMap) LockFunc(f func(m map[int]bool))
  16. func (this *IntBoolMap) RLockFunc(f func(m map[int]bool))
  17. func (this *IntBoolMap) Remove(key int) bool
  18. func (this *IntBoolMap) Set(key int, val bool)
  19. func (this *IntBoolMap) SetIfNotExist(key int, value bool) bool
  20. func (this *IntBoolMap) Size() int
  21. type IntIntMap
  22. func NewIntIntMap(safe ...bool) *IntIntMap
  23. func (this *IntIntMap) BatchRemove(keys []int)
  24. func (this *IntIntMap) BatchSet(m map[int]int)
  25. func (this *IntIntMap) Clear()
  26. func (this *IntIntMap) Clone() map[int]int
  27. func (this *IntIntMap) Contains(key int) bool
  28. func (this *IntIntMap) Get(key int) int
  29. func (this *IntIntMap) GetOrSet(key int, value int) int
  30. func (this *IntIntMap) GetOrSetFunc(key int, f func() int) int
  31. func (this *IntIntMap) GetOrSetFuncLock(key int, f func() int) int
  32. func (this *IntIntMap) IsEmpty() bool
  33. func (this *IntIntMap) Iterator(f func(k int, v int) bool)
  34. func (this *IntIntMap) Keys() []int
  35. func (this *IntIntMap) LockFunc(f func(m map[int]int))
  36. func (this *IntIntMap) RLockFunc(f func(m map[int]int))
  37. func (this *IntIntMap) Remove(key int) int
  38. func (this *IntIntMap) Set(key int, val int)
  39. func (this *IntIntMap) SetIfNotExist(key int, value int) bool
  40. func (this *IntIntMap) Size() int
  41. func (this *IntIntMap) Values() []int
  42. type IntInterfaceMap
  43. func NewIntInterfaceMap(safe ...bool) *IntInterfaceMap
  44. func (this *IntInterfaceMap) BatchRemove(keys []int)
  45. func (this *IntInterfaceMap) BatchSet(m map[int]interface{})
  46. func (this *IntInterfaceMap) Clear()
  47. func (this *IntInterfaceMap) Clone() map[int]interface{}
  48. func (this *IntInterfaceMap) Contains(key int) bool
  49. func (this *IntInterfaceMap) Get(key int) interface{}
  50. func (this *IntInterfaceMap) GetOrSet(key int, value interface{}) interface{}
  51. func (this *IntInterfaceMap) GetOrSetFunc(key int, f func() interface{}) interface{}
  52. func (this *IntInterfaceMap) GetOrSetFuncLock(key int, f func() interface{}) interface{}
  53. func (this *IntInterfaceMap) IsEmpty() bool
  54. func (this *IntInterfaceMap) Iterator(f func(k int, v interface{}) bool)
  55. func (this *IntInterfaceMap) Keys() []int
  56. func (this *IntInterfaceMap) LockFunc(f func(m map[int]interface{}))
  57. func (this *IntInterfaceMap) RLockFunc(f func(m map[int]interface{}))
  58. func (this *IntInterfaceMap) Remove(key int) interface{}
  59. func (this *IntInterfaceMap) Set(key int, val interface{})
  60. func (this *IntInterfaceMap) SetIfNotExist(key int, value interface{}) bool
  61. func (this *IntInterfaceMap) Size() int
  62. func (this *IntInterfaceMap) Values() []interface{}
  63. type IntStringMap
  64. func NewIntStringMap(safe ...bool) *IntStringMap
  65. func (this *IntStringMap) BatchRemove(keys []int)
  66. func (this *IntStringMap) BatchSet(m map[int]string)
  67. func (this *IntStringMap) Clear()
  68. func (this *IntStringMap) Clone() map[int]string
  69. func (this *IntStringMap) Contains(key int) bool
  70. func (this *IntStringMap) Get(key int) string
  71. func (this *IntStringMap) GetOrSet(key int, value string) string
  72. func (this *IntStringMap) GetOrSetFunc(key int, f func() string) string
  73. func (this *IntStringMap) GetOrSetFuncLock(key int, f func() string) string
  74. func (this *IntStringMap) IsEmpty() bool
  75. func (this *IntStringMap) Iterator(f func(k int, v string) bool)
  76. func (this *IntStringMap) Keys() []int
  77. func (this *IntStringMap) LockFunc(f func(m map[int]string))
  78. func (this *IntStringMap) RLockFunc(f func(m map[int]string))
  79. func (this *IntStringMap) Remove(key int) string
  80. func (this *IntStringMap) Set(key int, val string)
  81. func (this *IntStringMap) SetIfNotExist(key int, value string) bool
  82. func (this *IntStringMap) Size() int
  83. func (this *IntStringMap) Values() []string
  84. type InterfaceInterfaceMap
  85. func NewInterfaceInterfaceMap(safe ...bool) *InterfaceInterfaceMap
  86. func (this *InterfaceInterfaceMap) BatchRemove(keys []interface{})
  87. func (this *InterfaceInterfaceMap) BatchSet(m map[interface{}]interface{})
  88. func (this *InterfaceInterfaceMap) Clear()
  89. func (this *InterfaceInterfaceMap) Clone() map[interface{}]interface{}
  90. func (this *InterfaceInterfaceMap) Contains(key interface{}) bool
  91. func (this *InterfaceInterfaceMap) Get(key interface{}) interface{}
  92. func (this *InterfaceInterfaceMap) GetOrSet(key interface{}, value interface{}) interface{}
  93. func (this *InterfaceInterfaceMap) GetOrSetFunc(key interface{}, f func() interface{}) interface{}
  94. func (this *InterfaceInterfaceMap) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{}
  95. func (this *InterfaceInterfaceMap) IsEmpty() bool
  96. func (this *InterfaceInterfaceMap) Iterator(f func(k interface{}, v interface{}) bool)
  97. func (this *InterfaceInterfaceMap) Keys() []interface{}
  98. func (this *InterfaceInterfaceMap) LockFunc(f func(m map[interface{}]interface{}))
  99. func (this *InterfaceInterfaceMap) RLockFunc(f func(m map[interface{}]interface{}))
  100. func (this *InterfaceInterfaceMap) Remove(key interface{}) interface{}
  101. func (this *InterfaceInterfaceMap) Set(key interface{}, val interface{})
  102. func (this *InterfaceInterfaceMap) SetIfNotExist(key interface{}, value interface{}) bool
  103. func (this *InterfaceInterfaceMap) Size() int
  104. func (this *InterfaceInterfaceMap) Values() []interface{}
  105. type Map
  106. func New(safe ...bool) *Map
  107. type StringBoolMap
  108. func NewStringBoolMap(safe ...bool) *StringBoolMap
  109. func (this *StringBoolMap) BatchRemove(keys []string)
  110. func (this *StringBoolMap) BatchSet(m map[string]bool)
  111. func (this *StringBoolMap) Clear()
  112. func (this *StringBoolMap) Clone() map[string]bool
  113. func (this *StringBoolMap) Contains(key string) bool
  114. func (this *StringBoolMap) Get(key string) bool
  115. func (this *StringBoolMap) GetOrSet(key string, value bool) bool
  116. func (this *StringBoolMap) GetOrSetFunc(key string, f func() bool) bool
  117. func (this *StringBoolMap) GetOrSetFuncLock(key string, f func() bool) bool
  118. func (this *StringBoolMap) IsEmpty() bool
  119. func (this *StringBoolMap) Iterator(f func(k string, v bool) bool)
  120. func (this *StringBoolMap) Keys() []string
  121. func (this *StringBoolMap) LockFunc(f func(m map[string]bool))
  122. func (this *StringBoolMap) RLockFunc(f func(m map[string]bool))
  123. func (this *StringBoolMap) Remove(key string) bool
  124. func (this *StringBoolMap) Set(key string, val bool)
  125. func (this *StringBoolMap) SetIfNotExist(key string, value bool) bool
  126. func (this *StringBoolMap) Size() int
  127. type StringIntMap
  128. func NewStringIntMap(safe ...bool) *StringIntMap
  129. func (this *StringIntMap) BatchRemove(keys []string)
  130. func (this *StringIntMap) BatchSet(m map[string]int)
  131. func (this *StringIntMap) Clear()
  132. func (this *StringIntMap) Clone() map[string]int
  133. func (this *StringIntMap) Contains(key string) bool
  134. func (this *StringIntMap) Get(key string) int
  135. func (this *StringIntMap) GetOrSet(key string, value int) int
  136. func (this *StringIntMap) GetOrSetFunc(key string, f func() int) int
  137. func (this *StringIntMap) GetOrSetFuncLock(key string, f func() int) int
  138. func (this *StringIntMap) IsEmpty() bool
  139. func (this *StringIntMap) Iterator(f func(k string, v int) bool)
  140. func (this *StringIntMap) Keys() []string
  141. func (this *StringIntMap) LockFunc(f func(m map[string]int))
  142. func (this *StringIntMap) RLockFunc(f func(m map[string]int))
  143. func (this *StringIntMap) Remove(key string) int
  144. func (this *StringIntMap) Set(key string, val int)
  145. func (this *StringIntMap) SetIfNotExist(key string, value int) bool
  146. func (this *StringIntMap) Size() int
  147. func (this *StringIntMap) Values() []int
  148. type StringInterfaceMap
  149. func NewStringInterfaceMap(safe ...bool) *StringInterfaceMap
  150. func (this *StringInterfaceMap) BatchRemove(keys []string)
  151. func (this *StringInterfaceMap) BatchSet(m map[string]interface{})
  152. func (this *StringInterfaceMap) Clear()
  153. func (this *StringInterfaceMap) Clone() map[string]interface{}
  154. func (this *StringInterfaceMap) Contains(key string) bool
  155. func (this *StringInterfaceMap) Get(key string) interface{}
  156. func (this *StringInterfaceMap) GetOrSet(key string, value interface{}) interface{}
  157. func (this *StringInterfaceMap) GetOrSetFunc(key string, f func() interface{}) interface{}
  158. func (this *StringInterfaceMap) GetOrSetFuncLock(key string, f func() interface{}) interface{}
  159. func (this *StringInterfaceMap) IsEmpty() bool
  160. func (this *StringInterfaceMap) Iterator(f func(k string, v interface{}) bool)
  161. func (this *StringInterfaceMap) Keys() []string
  162. func (this *StringInterfaceMap) LockFunc(f func(m map[string]interface{}))
  163. func (this *StringInterfaceMap) RLockFunc(f func(m map[string]interface{}))
  164. func (this *StringInterfaceMap) Remove(key string) interface{}
  165. func (this *StringInterfaceMap) Set(key string, val interface{})
  166. func (this *StringInterfaceMap) SetIfNotExist(key string, value interface{}) bool
  167. func (this *StringInterfaceMap) Size() int
  168. func (this *StringInterfaceMap) Values() []interface{}
  169. type StringStringMap
  170. func NewStringStringMap(safe ...bool) *StringStringMap
  171. func (this *StringStringMap) BatchRemove(keys []string)
  172. func (this *StringStringMap) BatchSet(m map[string]string)
  173. func (this *StringStringMap) Clear()
  174. func (this *StringStringMap) Clone() map[string]string
  175. func (this *StringStringMap) Contains(key string) bool
  176. func (this *StringStringMap) Get(key string) string
  177. func (this *StringStringMap) GetOrSet(key string, value string) string
  178. func (this *StringStringMap) GetOrSetFunc(key string, f func() string) string
  179. func (this *StringStringMap) GetOrSetFuncLock(key string, f func() string) string
  180. func (this *StringStringMap) IsEmpty() bool
  181. func (this *StringStringMap) Iterator(f func(k string, v string) bool)
  182. func (this *StringStringMap) Keys() []string
  183. func (this *StringStringMap) LockFunc(f func(m map[string]string))
  184. func (this *StringStringMap) RLockFunc(f func(m map[string]string))
  185. func (this *StringStringMap) Remove(key string) string
  186. func (this *StringStringMap) Set(key string, val string)
  187. func (this *StringStringMap) SetIfNotExist(key string, value string) bool
  188. func (this *StringStringMap) Size() int
  189. func (this *StringStringMap) Values() []string

使用示例

  1. package main
  2. import (
  3. "fmt"
  4. "gitee.com/johng/gf/g/container/gmap"
  5. )
  6. func main() {
  7. // 创建一个默认的gmap对象,
  8. // 默认情况下该gmap对象支持并发安全特性,
  9. // 初始化时可以给定false参数关闭并发安全特性,当做一个普通的map使用。
  10. m := gmap.New()
  11. // 设置键值对
  12. for i := 0; i < 10; i++ {
  13. m.Set(i, i)
  14. }
  15. // 查询大小
  16. fmt.Println(m.Size())
  17. // 批量设置键值对(不同的数据类型对象参数不同)
  18. m.BatchSet(map[interface{}]interface{}{
  19. 10 : 10,
  20. 11 : 11,
  21. })
  22. fmt.Println(m.Size())
  23. // 查询是否存在
  24. fmt.Println(m.Contains(1))
  25. // 查询键值
  26. fmt.Println(m.Get(1))
  27. // 删除数据项
  28. m.Remove(9)
  29. fmt.Println(m.Size())
  30. // 批量删除
  31. m.BatchRemove([]interface{}{10, 11})
  32. fmt.Println(m.Size())
  33. // 当前键名列表(随机排序)
  34. fmt.Println(m.Keys())
  35. // 当前键值列表(随机排序)
  36. fmt.Println(m.Values())
  37. // 查询键名,当键值不存在时,写入给定的默认值
  38. fmt.Println(m.GetWithDefault(100, 100))
  39. // 删除键值对,并返回对应的键值
  40. fmt.Println(m.GetAndRemove(100))
  41. // 遍历map
  42. m.Iterator(func(k interface{}, v interface{}) bool {
  43. fmt.Printf("%v:%v ", k, v)
  44. return true
  45. })
  46. // 自定义写锁操作
  47. m.LockFunc(func(m map[interface{}]interface{}) {
  48. m[99] = 99
  49. })
  50. // 自定义读锁操作
  51. m.RLockFunc(func(m map[interface{}]interface{}) {
  52. fmt.Println(m[99])
  53. })
  54. // 清空map
  55. m.Clear()
  56. // 判断map是否为空
  57. fmt.Println(m.IsEmpty())
  58. }

执行后,输出结果为:

  1. 10
  2. 12
  3. true
  4. 1
  5. 11
  6. 9
  7. [0 1 2 4 6 7 3 5 8]
  8. [3 5 8 0 1 2 4 6 7]
  9. 100
  10. 100
  11. 3:3 5:5 8:8 7:7 0:0 1:1 2:2 4:4 6:6 99
  12. true

并发安全

gmap在默认情况下是并发安全的,但是在某些对性能要求比较高的场景下,又或者只是想使用gmap对象来便于操作map,那么用户可以选择主动关闭gmap的并发安全特性(必须在初始化时设定,不能运行时动态设定),性能会得到一定提升。关闭并发安全特性可以在创建gmap对象时传递false参数,如:

  1. m := gmap.New(false)

此外,即使在未开启并发安全特性的情况下,也可以使用Lock/RLock方法来并发安全地自定义操作gmap对象。

不仅仅是gmap,gf框架的其他并发安全数据结构也可以关闭并发安全特性,来提升性能或者简化原本复杂的数据结构操作。

性能测试

测试环境

  1. CPU: Intel(R) Core(TM) i5-4460 CPU @ 3.20GHz
  2. MEM: 8GB
  3. SYS: Ubuntu 16.04 amd64

并发安全

  1. n@john-B85M:~/Workspace/Go/GOPATH/src/gitee.com/johng/gf/g/container/gmap$ go test *.go -bench=".*" -benchmem
  2. goos: linux
  3. goarch: amd64
  4. Benchmark_IntBoolMap_Set-4 10000000 245 ns/op 38 B/op 0 allocs/op
  5. Benchmark_IntIntMap_Set-4 5000000 283 ns/op 53 B/op 0 allocs/op
  6. Benchmark_IntInterfaceMap_Set-4 5000000 320 ns/op 82 B/op 1 allocs/op
  7. Benchmark_IntStringMap_Set-4 5000000 342 ns/op 82 B/op 1 allocs/op
  8. Benchmark_InterfaceInterfaceMap_Set-4 3000000 363 ns/op 73 B/op 2 allocs/op
  9. Benchmark_StringBoolMap_Set-4 5000000 392 ns/op 62 B/op 1 allocs/op
  10. Benchmark_StringIntMap_Set-4 5000000 356 ns/op 56 B/op 1 allocs/op
  11. Benchmark_StringInterfaceMap_Set-4 3000000 361 ns/op 73 B/op 2 allocs/op
  12. Benchmark_StringStringMap_Set-4 3000000 385 ns/op 73 B/op 2 allocs/op
  13. Benchmark_IntBoolMap_Get-4 20000000 133 ns/op 0 B/op 0 allocs/op
  14. Benchmark_IntIntMap_Get-4 10000000 132 ns/op 0 B/op 0 allocs/op
  15. Benchmark_IntInterfaceMap_Get-4 10000000 137 ns/op 0 B/op 0 allocs/op
  16. Benchmark_IntStringMap_Get-4 10000000 147 ns/op 0 B/op 0 allocs/op
  17. Benchmark_InterfaceInterfaceMap_Get-4 10000000 155 ns/op 0 B/op 0 allocs/op
  18. Benchmark_StringBoolMap_Get-4 10000000 209 ns/op 7 B/op 0 allocs/op
  19. Benchmark_StringIntMap_Get-4 10000000 213 ns/op 7 B/op 0 allocs/op
  20. Benchmark_StringInterfaceMap_Get-4 10000000 242 ns/op 7 B/op 0 allocs/op
  21. Benchmark_StringStringMap_Get-4 10000000 267 ns/op 7 B/op 0 allocs/op

非并发安全

  1. john@john-B85M:~/Workspace/Go/GOPATH/src/gitee.com/johng/gf/g/container/gmap$ go test *.go -bench=".*" -benchmem
  2. goos: linux
  3. goarch: amd64
  4. Benchmark_Unsafe_IntBoolMap_Set-4 10000000 211 ns/op 38 B/op 0 allocs/op
  5. Benchmark_Unsafe_IntIntMap_Set-4 10000000 236 ns/op 62 B/op 0 allocs/op
  6. Benchmark_Unsafe_IntInterfaceMap_Set-4 5000000 279 ns/op 82 B/op 1 allocs/op
  7. Benchmark_Unsafe_IntStringMap_Set-4 5000000 304 ns/op 82 B/op 1 allocs/op
  8. Benchmark_Unsafe_InterfaceInterfaceMap_Set-4 10000000 488 ns/op 112 B/op 2 allocs/op
  9. Benchmark_Unsafe_StringBoolMap_Set-4 5000000 366 ns/op 62 B/op 1 allocs/op
  10. Benchmark_Unsafe_StringIntMap_Set-4 5000000 378 ns/op 56 B/op 1 allocs/op
  11. Benchmark_Unsafe_StringInterfaceMap_Set-4 3000000 472 ns/op 73 B/op 2 allocs/op
  12. Benchmark_Unsafe_StringStringMap_Set-4 2000000 510 ns/op 96 B/op 2 allocs/op
  13. Benchmark_Unsafe_IntBoolMap_Get-4 20000000 110 ns/op 0 B/op 0 allocs/op
  14. Benchmark_Unsafe_IntIntMap_Get-4 20000000 111 ns/op 0 B/op 0 allocs/op
  15. Benchmark_Unsafe_IntInterfaceMap_Get-4 20000000 122 ns/op 0 B/op 0 allocs/op
  16. Benchmark_Unsafe_IntStringMap_Get-4 20000000 118 ns/op 0 B/op 0 allocs/op
  17. Benchmark_Unsafe_InterfaceInterfaceMap_Get-4 10000000 230 ns/op 0 B/op 0 allocs/op
  18. Benchmark_Unsafe_StringBoolMap_Get-4 10000000 200 ns/op 7 B/op 0 allocs/op
  19. Benchmark_Unsafe_StringIntMap_Get-4 10000000 202 ns/op 7 B/op 0 allocs/op
  20. Benchmark_Unsafe_StringInterfaceMap_Get-4 10000000 218 ns/op 7 B/op 0 allocs/op
  21. Benchmark_Unsafe_StringStringMap_Get-4 10000000 200 ns/op 7 B/op 0 allocs/op

gmap与sync.Map

go语言从1.9版本开始引入了并发安全的sync.Map,我们来看看基准测试结果:

  1. john@john-B85M:~/Workspace/Go/GOPATH/src/gitee.com/johng/gf/g/container/gmap$ go test *.go -bench=".*" -benchmem
  2. goos: linux
  3. goarch: amd64
  4. BenchmarkGmapSet-4 10000000 324 ns/op 62 B/op 0 allocs/op
  5. BenchmarkSyncmapSet-4 2000000 697 ns/op 105 B/op 4 allocs/op
  6. BenchmarkGmapGet-4 10000000 149 ns/op 0 B/op 0 allocs/op
  7. BenchmarkSyncmapGet-4 10000000 154 ns/op 0 B/op 0 allocs/op
  8. BenchmarkGmapRemove-4 10000000 126 ns/op 0 B/op 0 allocs/op
  9. BenchmarkSyncmapRmove-4 10000000 118 ns/op 0 B/op 0 allocs/op

可以看到,在写入/删除这块gmap的性能与标准库的sync.Map对象没有差别,但在写入这块性能优势比较明显。