Cuando utiliza un mapa en un programa con acceso simultáneo, ¿hay alguna necesidad de utilizar un mutex en las funciones para leer los valores?Mapa con acceso simultáneo
Respuesta
múltiples lectores, escritores no está bien:
https://groups.google.com/d/msg/golang-nuts/HpLWnGTp-n8/hyUYmnWJqiQJ
Un escritor, no hay lectores está bien. (Los mapas no sería mucho más bueno de lo contrario.)
De lo contrario, si hay al menos un escritor y al menos uno más, ya sea escritor o lector, entonces todos los lectoresy escritores deben utilizar la sincronización para acceder al mapa . Un mutex funciona bien para esto.
me respondió su pregunta en this hilo reddit Hace pocos días:
En Go, los mapas no son seguros para subprocesos. Además, los datos requieren el bloqueo incluso para leyendo si, por ejemplo, podría haber otra goroutine que es escribiendo los mismos datos (al mismo tiempo, eso es).
A juzgar por su aclaración en los comentarios, que también van a haber funciones de colocador, la respuesta a su pregunta es sí, tendrá que proteger sus lecturas con un mutex; puede usar un RWMutex. Para un ejemplo, puede ver el source de la implementación de una estructura de datos de tablas (utiliza un mapa detrás de las escenas) que escribí (en realidad, el vinculado en el hilo de reddit).
Por lo general, es un desperdicio utilizar un bloqueo de lector-escritor completo para un recurso tan rápido de acceder como un mapa – rmmh
¿Puede elaborar un poco por favor? ¿Qué sería mejor? –
Los bloqueos de RW son buenos para recursos con mucha controversia, pero tienen más sobrecarga que un mutex. Los get/sets del mapa son lo suficientemente rápidos como para que el programa no tenga suficiente contención para hacer que el bloqueo más complejo dé un mejor rendimiento que un simple mutex. – rmmh
Puede usar concurrent-map para controlar los problemas de concurrencia.
// 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")
Cosas como esta son las razones por las que no puedo tomar en serio la noción de "no". necesitan genéricos ". – Lucretiel
La idea no es que Go "no necesite genéricos", sino que "actualmente no hay una forma clara de implementar genéricos, tenemos que pensar un poco más". C++, por ejemplo, genera código para todas las posibles combinaciones de tipos que se utilizan, lo que aumenta los tiempos de compilación y los tamaños de los ejecutables en una cantidad irracional. – Alexander
si solo tiene un escritor, entonces probablemente pueda salirse con la suya con un valor atómico. La siguiente es una adaptación de https://golang.org/pkg/sync/atomic/#example_Value_readMostly (el original utiliza bloqueos para proteger la escritura, por lo que es compatible con varios escritores)
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.
}
sync.Map
ha fusionado a libre Maestro el 27 de abril, 2017.
Este es el mapa de concurrentes que todos han estado esperando.
Bueno. Tenga en cuenta que el nuevo tipo de Sync.Map está diseñado para mapas de solo anexar (por esta razón no usa la fusión de claves, lo que significa que si su mapa tiene mucha rotación, lo más probable es que rinda por debajo de los mapas de estilo fragmentados según mi respuesta arriba). – orcaman
@orcaman, ¿qué quieres decir con mapas de solo apéndice? – OmarIlias
@OmarIlias me refiero a casos en los que establece principalmente nuevos valores (sin editar ni eliminar valores existentes). Vea esto: https://github.com/golang/go/issues/20360 – orcaman
¿Por qué no se hizo uso de Go modelo de concurrencia en su lugar, hay un ejemplo sencillo ...
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
}
- 1. PHP y acceso simultáneo a archivos
- 2. acceso simultáneo a un método estático utilidad
- 3. ¿Cómo administrar el desarrollo simultáneo con mercurial?
- 4. procesamiento simultáneo/peticiones asíncronas con BaseHTTPServer Python
- 5. std :: mapa con acceso eficiente a elemento n
- 6. C++ descarta mapa de acceso calificadores (const)
- 7. Aborto simultáneo() en dos hilos
- 8. C++ const acceso a elemento de mapa
- 9. Desplazamiento simultáneo de dos UITableViews
- 10. ¿Cómo se maneja el acceso simultáneo a una colección de Scala?
- 11. La mejor forma de controlar el acceso simultáneo a las colecciones de Java
- 12. Cuáles son las reglas sobre el acceso simultáneo a una base de datos persistente
- 13. Boost Puntero compartido: acceso de lectura simultáneo a través de varios subprocesos
- 14. El acceso simultáneo a la matriz compartida es un problema en Node.js
- 15. Android - Audio múltiple y simultáneo Streaming
- 16. Matplotlib: trazado simultáneo en múltiples hilos
- 17. MSMQ problema de diseño de procesamiento simultáneo
- 18. NSOperationQueue y concurrente versus no simultáneo
- 19. Mapa de acceso <Enum, objeto> en JSTL
- 20. ¿Valor de mapa de acceso a través del índice?
- 21. Problema con el mapa()
- 22. Mapa mundial con ggmap
- 23. Acceso al atributo Mapa con clave dinámica en Struts 2 OGNL
- 24. conjunto múltiple, mapa y mapa hash complejidad
- 25. Re: acceso de referencia con boost :: make_transform_iterator
- 26. ¿Cómo serializar un mapa de un mapa con GSON?
- 27. Desarrollo simultáneo en Visual Studio y Qt Creator
- 28. Hash con acceso indiferente
- 29. Imprimir mapa con capa propia
- 30. mapa de ggplot con l
Si es estrictamente un mapa de sólo lectura, un mutex no debería ser necesario. – jimt
No estaba muy claro ya que habrá funciones para establecer y obtener valores. –