-4

Everyone is saying write/read golang map concurrently is not safe, but can we just update it but not write new keys?

We know code below would cause fatal error: concurrent map read and map write.

var m = make(map[int]int)

for i := 0; i < 1000; i++ {
    go func() {
        m[i] = i
    }()
}

Now I'm wondering if we can update map concurrently as below.

var m = make(map[int]int)

// init memory structure of map
for i := 0; i < 1000; i++ {
    m[i] = 0
}

// just update values for old keys concurrently
for i := 0; i < 1000; i++ {
    go func() {
        m[i] = i
    }()
}

Can we do that?

  • 2
    See [How to recover from concurrent map writes?](https://stackoverflow.com/questions/39288741/how-to-recover-from-concurrent-map-writes/39289246?r=SearchResults#39289246) – icza Oct 23 '19 at 09:57
  • 1
    Don't do it, even if it happens to work with the current compiler. The runtime is free to re-arrange maps in memory on any update, independent of whether a new key is inserted or an existing key updated, so what works today may break tomorrow. Maps are not safe for concurrent read-write access, period. – Peter Oct 23 '19 at 10:13
  • 1
    "can we just update it but not write new keys?" No. Updating an existing key is still a write. – Adrian Oct 23 '19 at 13:23

1 Answers1

3

Can we do that?

No, of course not. It just produces a runtime error "fatal error: concurrent map writes" (with literally your code, so you could have tried it yourself).

Just stop fighting the language and trying to be clever: No concurrent writes (not even "clever" ones)!

Volker
  • 40,468
  • 7
  • 81
  • 87
  • 1
    OP uses closures incorrectly though. If you pass the index to the goroutine as a parameter, it does not crash: https://play.golang.org/p/2PKUlzAZFod – Clément Oct 23 '19 at 09:52
  • 1
    But then, both ways described by OP work, so not sure if that proves anything: https://play.golang.org/p/6oPO8a5TOl5 – Clément Oct 23 '19 at 10:04