Карты сами по себе не заботятся о блокировках, поэтому любая манипуляция ими при выполнении нескольких операций (или чтение во время манипуляции) потребует некоторой синхронизации (например, sync.Mutex
).Хотя есть и более причудливые вещи, которые вы можете сделать.
RW Mutex
В зависимости от вашего варианта использования вы можете получить немного более изящного использования и использовать sync.RWMutex
.Это позволит одновременное чтение, в то же время безопасно блокируя любую запись.Например:
package main
import (
"sync"
"time"
)
func main() {
m := map[int]int{}
lock := sync.RWMutex{}
go func() {
// Writer
for range time.Tick(250 * time.Millisecond) {
// Notice that this uses Lock and NOT RLock
lock.Lock()
m[5]++
m[6] += 2
lock.Unlock()
}
}()
go func() {
for range time.Tick(250 * time.Millisecond) {
lock.RLock()
println(m[5])
lock.RUnlock()
}
}()
for range time.Tick(250 * time.Millisecond) {
lock.RLock()
println(m[6])
lock.RUnlock()
}
}
Это не дает вам механизм блокировки ключей.
sync.Map
sync.Map
предоставляется стандартной библиотекой и является надежным.У него более точная блокировка.
package main
import (
"sync"
"time"
)
func main() {
m := sync.Map{}
go func() {
// Writer
for range time.Tick(250 * time.Millisecond) {
value, _ := m.LoadOrStore(5, 0)
m.Store(5, value.(int)+1)
value, _ = m.LoadOrStore(6, 0)
m.Store(6, value.(int)+2)
}
}()
go func() {
for range time.Tick(250 * time.Millisecond) {
value, _ := m.LoadOrStore(5, 0)
println(value.(int))
}
}()
for range time.Tick(250 * time.Millisecond) {
value, _ := m.LoadOrStore(6, 0)
println(value.(int))
}
}
Обратите внимание, что в коде нет мьютексов.Также обратите внимание, что вы имеете дело с пустыми интерфейсами ...