请注意,本文为作者原创。
Notice that the article is originally created by the author. Please indicate the source when reshipped.
What if two goroutines concurrently write to the same map in golang? let us see a simple example below,
package main
import (
"strconv"
"sync"
)
func worker(wg *sync.WaitGroup, m map[string]string) {
defer wg.Done()
for i := 0; i < 1000000; i++ {
m[strconv.Itoa(i)] = strconv.Itoa(i)
}
}
func main() {
m := make(map[string]string)
var wg sync.WaitGroup
wg.Add(1)
go worker(&wg, m)
for i := 0; i < 1000000; i++ {
m[strconv.Itoa(i)] = strconv.Itoa(i)
}
wg.Wait()
}
when run, the code panics with the fatal error below,
fatal error: concurrent map writes
Golang does not allow a map to be written concurrently by mulitple goroutines, if you want to do so, concurrent map is a better choice, or you can add mutex lock before writing to a map concurrently. So the code above may be changed like this,
package main
import (
"fmt"
"strconv"
"sync"
)
func worker(wg *sync.WaitGroup, m map[string]string, mutex *sync.RWMutex) {
defer wg.Done()
for i := 0; i < 1000000; i++ {
mutex.Lock()
m[strconv.Itoa(i)] = strconv.Itoa(i)
mutex.Unlock()
}
}
func main() {
m := make(map[string]string)
var wg sync.WaitGroup
var mutex sync.RWMutex
wg.Add(1)
go worker(&wg, m, &mutex)
for i := 0; i < 1000000; i++ {
mutex.Lock()
m[strconv.Itoa(i)] = strconv.Itoa(i)
mutex.Unlock()
}
wg.Wait()
for k, v := range m {
fmt.Println(k, v)
}
}
Or in another way, we can use the open source concurrent map package to implement safe concurrently writing.
Please note, if one goroutine is writing to the map, meanwhile another goroutine is reading the same map, the mutex lock is also needed here to guarantee safely concurrent access.