Concurrent Access to Map Values?

110 views
Skip to first unread message

jlfo...@berkeley.edu

unread,
Jul 28, 2026, 12:14:37 PM (21 hours ago) Jul 28
to golang-nuts
(I posted this to r/golang but I didn't get what I consider a definitive answer).

I know that maps aren't safe for concurrent access, but I've always thought this meant only that you can't add or delete keys concurrently.

Let's say I already have a map[string]int that has been filled with keys that are file names. I won't be adding any more keys. I want to add an int value for each existing key to contain the file size. Could I do this by running a bunch of go routines, one per file name key? (Let's ignore for now whether doing this would be any faster than not using go routines.)

The Go Language spec doesn't directly define the rules for concurrent memory safety. Instead, those rules are explicitly defined in the Go Memory Model (https://go.dev/ref/mem). I looked there but I wasn't able to find what I was looking for.  The Go FAQ has a section on Atomic Maps (https://go.dev/doc/faq#atomic_maps) says 

"As long as all goroutines are only reading—looking up elements in the map, including iterating through it using a for range loop—and not changing the map by assigning to elements or doing deletions, it is safe for them to access the map concurrently without synchronization."

The question here is what is meant by "assigning to elements".

My thinking is that this should be allowed because adding a file name to the map should have also added space for an int value. So, I'd just be modifying this int, and not changing the hash table data structure. Is this correct?


Cordially,

Jon Forrest



robert engels

unread,
Jul 28, 2026, 1:16:01 PM (20 hours ago) Jul 28
to jlfo...@berkeley.edu, golang-nuts
You are assigning to elements, so no, not allowed. If you have a system where you know all of the keys ahead of time there are much better data structures to use for something like this - simple atomic read and write of the values. 

On Jul 28, 2026, at 11:15 AM, 'jlfo...@berkeley.edu' via golang-nuts <golan...@googlegroups.com> wrote:


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/873345e3-4dc6-4578-a408-b356f3ab04abn%40googlegroups.com.

Ian Lance Taylor

unread,
Jul 28, 2026, 4:04:13 PM (18 hours ago) Jul 28
to jlfo...@berkeley.edu, golang-nuts
The Go memory model prohibits concurrent reads and writes, or
concurrent writes, to variables. A map is a variable. You can't
concurrently modify either the key or the value of a map.

What you can do is store a pointer in the map. Then you can modify the
fields to which that pointer points as you wish. Of course you have to
avoid concurrent modifications of those memory locations, but that
doesn't matter if each element is only modified by a single goroutine.

Ian

robert engels

unread,
Jul 28, 2026, 10:51:16 PM (11 hours ago) Jul 28
to Ian Lance Taylor, jlfo...@berkeley.edu, golang-nuts
I don’t think that is true. You still need to use atomics or locks to modify the values even with a single writer, or there’s no guarantee a reader will see the updated value ever.

> On Jul 28, 2026, at 3:04 PM, Ian Lance Taylor <ia...@golang.org> wrote:
>
> On Tue, Jul 28, 2026 at 9:15 AM 'jlfo...@berkeley.edu' via golang-nuts
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcXoVnqDhF2n5rYMPACpLZmwWROt%3DQCAkVXRqucnj4D%3D4w%40mail.gmail.com.

Ian Lance Taylor

unread,
12:20 AM (9 hours ago) 12:20 AM
to robert engels, jlfo...@berkeley.edu, golang-nuts
On Tue, Jul 28, 2026 at 7:50 PM robert engels <rob...@me.com> wrote:
>
> I don’t think that is true. You still need to use atomics or locks to modify the values even with a single writer, or there’s no guarantee a reader will see the updated value ever.

What I mean is that it is OK to write this:

https://go.dev/play/p/Mw7lP7ElPQ_a

package main

import (
"fmt"
"sync"
)

func main() {
m := map[string]*int{
"a": new(1),
"b": new(2),
}
var wg sync.WaitGroup
for k := range m {
wg.Go(func() {
(*m[k])++
})
}
wg.Wait()
for k, v := range m {
fmt.Println(k, *v)
}
}


Ian

robert engels

unread,
12:36 AM (9 hours ago) 12:36 AM
to Ian Lance Taylor, jlfo...@berkeley.edu, golang-nuts
That code is correct, and matches the OPs scenario, but it goes beyond your original constraints which was that they “are not concurrently written to”. With that code, you are also synchronizing any reads with the mutators - which is what I was trying to clarify.

> On Jul 28, 2026, at 11:19 PM, Ian Lance Taylor <ia...@golang.org> wrote:

Touring Tim

unread,
1:32 AM (8 hours ago) 1:32 AM
to robert engels, Ian Lance Taylor, jlfo...@berkeley.edu, golang-nuts
I'm sure you should put a lock if changing v, I have similar maps and always lock when writing to it and rlock when reading.

For me a completely static map initialised and k,v set, is one that needs no lock to read concurrently.

Haddock

unread,
3:29 AM (6 hours ago) 3:29 AM
to golang-nuts
Java has a segmented concurrent hash map, see  java - In ConcurrentHashMap how the segments are defined - Stack Overflow where each segment is thread safe. So you when values of keys in different segments are accessed access can happen concurrently which improves throughput.

Haddock

unread,
5:59 AM (4 hours ago) 5:59 AM
to golang-nuts
Forgot to mention: The current implementation of ConcurrentHashMap in the more recent JDKs is quite optimized and it is meanwhile hard to see what it does. If you take an older JDK (JDK8 or upwards, not sure  ConcurrentHashMap already exists in JDK8) you see an older implementation with an array of 16 segments and some algorithm that from the key derives a number between 0 and 15. That approach is easy to implement in some other language.

robert engels

unread,
8:36 AM (1 hour ago) 8:36 AM
to Haddock, golang-nuts
This may be of interest to some. Shows some specific implementations of some concurrent structures. https://github.com/robaho/go-concurrency-test

On Jul 29, 2026, at 5:00 AM, Haddock <bienle...@gmail.com> wrote:

Forgot to mention: The current implementation of ConcurrentHashMap in the more recent JDKs is quite optimized and it is meanwhile hard to see what it does. If you take an older JDK (JDK8 or upwards, not sure  ConcurrentHashMap already exists in JDK8) you see an older implementation with an array of 16 segments and some algorithm that from the key derives a number between 0 and 15. That approach is easy to implement in some other language.
Reply all
Reply to author
Forward
0 new messages