Map with concurrent access - Stack Overflow most recent 30 from stackoverflow.com 2026-04-14T14:26:28Z https://stackoverflow.com/feeds/question/11063473 https://creativecommons.org/licenses/by-sa/4.0/rdf https://stackoverflow.com/q/11063473 96 Map with concurrent access user1243746 https://stackoverflow.com/users/0 2012-06-16T12:35:20Z 2018-09-04T08:02:37Z <p>When you use a map in a program with concurrent access, is there any need to use a mutex in functions to <strong>read</strong> values?</p> https://stackoverflow.com/questions/11063473/-/11063566#11063566 124 Answer by Sonia for Map with concurrent access Sonia https://stackoverflow.com/users/620399 2012-06-16T12:47:14Z 2012-06-16T16:30:58Z <p>Multiple readers, no writers is okay:</p> <p><a href="https://groups.google.com/d/msg/golang-nuts/HpLWnGTp-n8/hyUYmnWJqiQJ">https://groups.google.com/d/msg/golang-nuts/HpLWnGTp-n8/hyUYmnWJqiQJ</a></p> <p>One writer, no readers is okay. (Maps wouldn't be much good otherwise.)</p> <p>Otherwise, if there is at least one writer and at least one more either writer or reader, then <strong>all</strong> readers <strong>and</strong> writers must use synchronization to access the map. A mutex works fine for this.</p> https://stackoverflow.com/questions/11063473/-/11066001#11066001 25 Answer by user11617 for Map with concurrent access user11617 https://stackoverflow.com/users/0 2012-06-16T18:27:59Z 2012-08-27T10:04:56Z <p>I answered your question in <a href="http://www.reddit.com/r/programming/comments/uw28d/samling_a_threadsafe_table_data_structure/">this</a> reddit thread few days ago:</p> <blockquote> <p>In Go, maps are not thread-safe. Also, data requires locking even for reading if, for example, there could be another goroutine that is writing the same data (concurrently, that is).</p> </blockquote> <p>Judging by your clarification in the comments, that there are going to be setter functions too, the answer to your question is yes, you will have to protect your reads with a mutex; you can use a <a href="http://golang.org/pkg/sync/#RWMutex">RWMutex</a>. For an example you can look at the <a href="https://github.com/noll/samling/blob/master/table/table.go">source</a> of the implementation of a table data structure (uses a map behind the scenes) which I wrote (actually the one linked in the reddit thread).</p> https://stackoverflow.com/questions/11063473/-/26204893#26204893 23 Answer by orcaman for Map with concurrent access orcaman https://stackoverflow.com/users/2534777 2014-10-05T16:49:20Z 2016-10-20T09:25:20Z <p>You could use <a href="https://github.com/orcaman/concurrent-map" rel="noreferrer">concurrent-map</a> to handle the concurrency pains for you. </p> <pre><code>// 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") </code></pre> https://stackoverflow.com/questions/11063473/-/41511922#41511922 3 Answer by Martyn Weber for Map with concurrent access Martyn Weber https://stackoverflow.com/users/7385296 2017-01-06T18:23:48Z 2017-01-06T18:23:48Z <p>if you only have one writer, then you can probably get away with using an atomic Value. The following is adapted from <a href="https://golang.org/pkg/sync/atomic/#example_Value_readMostly" rel="nofollow noreferrer">https://golang.org/pkg/sync/atomic/#example_Value_readMostly</a> (the original uses locks to protect writing, so supports multiple writers)</p> <pre><code>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. } </code></pre> https://stackoverflow.com/questions/11063473/-/43678225#43678225 70 Answer by Qubitium for Map with concurrent access Qubitium https://stackoverflow.com/users/1897249 2017-04-28T10:40:11Z 2017-09-27T22:54:08Z <p><code>sync.Map</code> has merged to Go master as of April 27, 2017.</p> <p>This is the concurrent Map we have all been waiting for. </p> <p><a href="https://github.com/golang/go/blob/master/src/sync/map.go" rel="noreferrer">https://github.com/golang/go/blob/master/src/sync/map.go</a></p> <p><a href="https://godoc.org/sync#Map" rel="noreferrer">https://godoc.org/sync#Map</a></p> https://stackoverflow.com/questions/11063473/-/48956497#48956497 1 Answer by user3215378 for Map with concurrent access user3215378 https://stackoverflow.com/users/3215378 2018-02-23T21:30:58Z 2018-02-23T21:39:13Z <p>Why no made use of Go concurrency model instead, there is a simple example...</p> <pre><code>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 := &lt;-dataManager.m_dataStoreChan: if op["op"] == "getDataStore" { storeId := op["storeId"].(string) op["store"].(chan DataStore) &lt;- 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) &lt;- 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 &lt;- arguments return &lt;-result } func (this *DataManager) getDataStores() []DataStore { arguments := make(map[string]interface{}) arguments["op"] = "getDataStores" result := make(chan []DataStore) arguments["stores"] = result this.m_dataStoreChan &lt;- arguments return &lt;-result } func (this *DataManager) setDataStore(store DataStore) { arguments := make(map[string]interface{}) arguments["op"] = "setDataStore" arguments["store"] = store this.m_dataStoreChan &lt;- arguments } func (this *DataManager) removeDataStore(id string) { arguments := make(map[string]interface{}) arguments["storeId"] = id arguments["op"] = "removeDataStore" this.m_dataStoreChan &lt;- arguments } </code></pre>