Карта с одновременным доступом

Когда вы используете карту в программе с параллельным доступом, нужно ли использовать мьютекс в функциях для чтения значений?

Множество читателей, нет писателей в порядке:

https://groups.google.com/d/msg/golang-nuts/HpLWnGTp-n8/hyUYmnWJqiQJ

Один писатель, без читателей. (Карты были бы не очень хорошими в противном случае.)

В противном случае, если есть хотя бы один писатель и, по крайней мере, еще один писатель или читатель, все читатели и писатели должны использовать синхронизацию для доступа к карте. Мьютекс отлично подходит для этого.

sync.Map объединилась с Go master по состоянию на 27 апреля 2017 года.

Это параллельная Карта, которую мы все ждали.

https://github.com/golang/go/blob/master/src/sync/map.go

https://godoc.org/sync#Map

Я ответил на ваш вопрос в этой красноречивой теме несколько дней назад:

В Go карты не являются streamобезопасными. Кроме того, данные требуют блокировки даже для чтения, если, например, может быть другой goroutine, который пишет одни и те же данные (одновременно, то есть).

Судя по вашим пояснениям в комментариях, что будут и функции setter, ответ на ваш вопрос – да, вам придется защищать ваши чтения с помощью мьютекса; вы можете использовать RWMutex . В качестве примера вы можете посмотреть на источник реализации структуры данных таблицы (использует карту за кулисами), которую я написал (фактически тот, что связан в streamе reddit).

Вы можете использовать параллельную карту для обработки бонусов параллелизма для вас.

 // 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") 

если у вас есть только один писатель, то вы, вероятно, можете уйти от использования атомного значения. Ниже приведено 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. } 

Почему бы не использовать модель параллелизма Go вместо этого, есть простой пример …

 type DataManager struct { /** This contain connection to know dataStore **/ m_dataStores map[string]DataStore /** That channel is use to access the dataStores map **/ m_dataStoreChan chan map[string]interface{} } func newDataManager() *DataManager { dataManager := new(DataManager) dataManager.m_dataStores = make(map[string]DataStore) dataManager.m_dataStoreChan = make(chan map[string]interface{}, 0) // Concurrency... go func() { for { select { case op := <-dataManager.m_dataStoreChan: if op["op"] == "getDataStore" { storeId := op["storeId"].(string) op["store"].(chan DataStore) <- dataManager.m_dataStores[storeId] } else if op["op"] == "getDataStores" { stores := make([]DataStore, 0) for _, store := range dataManager.m_dataStores { stores = append(stores, store) } op["stores"].(chan []DataStore) <- stores } else if op["op"] == "setDataStore" { store := op["store"].(DataStore) dataManager.m_dataStores[store.GetId()] = store } else if op["op"] == "removeDataStore" { storeId := op["storeId"].(string) delete(dataManager.m_dataStores, storeId) } } } }() return dataManager } /** * Access Map functions... */ func (this *DataManager) getDataStore(id string) DataStore { arguments := make(map[string]interface{}) arguments["op"] = "getDataStore" arguments["storeId"] = id result := make(chan DataStore) arguments["store"] = result this.m_dataStoreChan <- arguments return <-result } func (this *DataManager) getDataStores() []DataStore { arguments := make(map[string]interface{}) arguments["op"] = "getDataStores" result := make(chan []DataStore) arguments["stores"] = result this.m_dataStoreChan <- arguments return <-result } func (this *DataManager) setDataStore(store DataStore) { arguments := make(map[string]interface{}) arguments["op"] = "setDataStore" arguments["store"] = store this.m_dataStoreChan <- arguments } func (this *DataManager) removeDataStore(id string) { arguments := make(map[string]interface{}) arguments["storeId"] = id arguments["op"] = "removeDataStore" this.m_dataStoreChan <- arguments } 

Моя простая реализация:

 import ( "sync" ) type AtomicMap struct { data map[string]string rwLock sync.RWMutex } func (self *AtomicMap) Get(key string) (string, bool) { self.rwLock.RLock() defer self.rwLock.RUnlock() val, found := self.data[key] return val, found } func (self *AtomicMap) Set(key, val string) { self.rwLock.Lock() defer self.rwLock.Unlock() self.data[key] = val } 
  • Разница между HashMap, LinkedHashMap и TreeMap
  • Как элементы заказа Java в HashMap или HashTable?
  • Отображение MapView с отсутствующими fragmentами с «x» в центре
  • Какой идеальный тип данных используется при хранении широты / долготы в базе данных MySQL?
  • Выбор между std :: map и std :: unordered_map
  • Архитектуры для доступа к смарт-карте из общего браузера? Или: как устранить разрыв между браузером и ПК / SC?
  • Interesting Posts

    Восстановление потерянного раздела NTFS с поврежденным загрузочным сектором

    React не перезагружает данные компонента при изменении параметров маршрута или изменении запроса

    Как реализовать wordwrap на jqGrid, который работает на IE7, IE8 и FF

    Ограничение доступа: недоступно из-за ограничений на требуемую библиотеку. \ Jre \ lib \ rt.jar

    Параметры sshd и -i для OS X

    Как я могу реализовать функции ослабления с помощью streamа

    Добавление пространства между столбцами в ggplot2

    Преобразование VB6 в VB.net

    OpenSubKey () возвращает null для ключа реестра, который я могу видеть в regedit.exe

    HTTP GET с телом запроса

    Разбор строки по дате формата в java defaults датируется 1 и месяц до января

    Является ли идентификатор fragmentа URL-адреса отправленным на сервер?

    В чем смысл гибкости streamов в ASP.Net?

    Наиболее общее ограничение высшего порядка, описывающее последовательность целых чисел, упорядоченных относительно отношения

    Как изменить перспективу после завершения отлаженного процесса в Eclipse?

    Давайте будем гением компьютера.