Когда вы используете карту в программе с параллельным доступом, нужно ли использовать мьютекс в функциях для значений читать?
Карта с одновременным доступом
Ответ 1
Несколько читателей, нет писателей в порядке:
https://groups.google.com/d/msg/golang-nuts/HpLWnGTp-n8/hyUYmnWJqiQJ
Один писатель, нет читателей. (Карты были бы не очень хорошими в противном случае.)
В противном случае, если есть хотя бы один писатель и, по крайней мере, еще один писатель или читатель, тогда все читатели и должны использовать синхронизацию для доступа к карте. Мьютекс отлично работает для этого.
Ответ 2
sync.Map
с 27 апреля 2017 года слился с Go-хозяином.
Это параллельная Карта, которую мы все ждали.
Ответ 3
Я ответил на ваш вопрос в этом reddit thread несколько дней назад:
В Go карты не являются потокобезопасными. Кроме того, данные требуют блокировки даже для если, к примеру, может быть другой горутин, который записывая одни и те же данные (одновременно).
Судя по вашим пояснениям в комментариях, что также будут функции setter, ответ на ваш вопрос - да, вам придется защищать ваши чтения с помощью мьютекса; вы можете использовать RWMutex. В качестве примера вы можете посмотреть источник реализации структуры данных таблицы (использует карту за кулисами), которую я написал (на самом деле тот, который связан в reddit нить).
Ответ 4
Вы можете использовать concurrent-map для обработки усилий concurrency для вас.
// Create a new map.
map := cmap.NewConcurrentMap()
// Add item to map, adds "bar" under key "foo"
map.Add("foo", "bar")
// Retrieve item from map.
tmp, ok := map.Get("foo")
// Checks if item exists
if ok == true {
// Map stores items as interface{}, hence we'll have to cast.
bar := tmp.(string)
}
// Removes item under key "foo"
map.Remove("foo")
Ответ 5
Если у вас есть только один писатель, тогда вы, вероятно, можете уйти от использования атомного значения. Ниже приведено https://golang.org/pkg/sync/atomic/#example_Value_readMostly (оригинал использует блокировки для защиты записи, поэтому поддерживает несколько авторов)
type Map map[string]string
var m Value
m.Store(make(Map))
read := func(key string) (val string) { // read from multiple go routines
m1 := m.Load().(Map)
return m1[key]
}
insert := func(key, val string) { // update from one go routine
m1 := m.Load().(Map) // load current value of the data structure
m2 := make(Map) // create a new map
for k, v := range m1 {
m2[k] = v // copy all data from the current object to the new one
}
m2[key] = val // do the update that we need (can delete/add/change)
m.Store(m2) // atomically replace the current object with the new one
// At this point all new readers start working with the new version.
// The old version will be garbage collected once the existing readers
// (if any) are done with it.
}