The map is not safe for concurrent use by default, and when performing concurrent read and write operations on a map, the program will panic for the following reasons:
After a long discussion, the Go team believes that Go maps should better fit typical usage scenarios (where safe access from multiple goroutines is not required) rather than catering to a small number of cases (concurrent access), which would impose locking costs (performance) on most programs, leading to the decision not to support it.
Scenario: Two goroutines reading and writing simultaneously, the following program will produce a fatal error: fatal error: concurrent map writes
package main
import (
"fmt"
"time"
)
func main() {
s := make(map[int]int)
for i := 0; i < 100; i++ {
go func(i int) {
s[i] = i
}(i)
}
for i := 0; i < 100; i++ {
go func(i int) {
fmt.Printf("The value of the %dth element in the map is %d\n", i, s[i])
}(i)
}
time.Sleep(1 * time.Second)
}
If you want to achieve thread-safe maps, there are two ways:
Method 1: Use a read-write lock map + sync.RWMutex
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var lock sync.RWMutex
s := make(map[int]int)
for i := 0; i < 100; i++ {
go func(i int) {
lock.Lock()
s[i] = i
lock.Unlock()
}(i)
}
for i := 0; i < 100; i++ {
go func(i int) {
lock.RLock()
fmt.Printf("The value of the %dth element in the map is %d\n", i, s[i])
lock.RUnlock()
}(i)
}
time.Sleep(1 * time.Second)
}
Method 2: Use the sync.Map provided by Go
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var m sync.Map
for i := 0; i < 100; i++ {
go func(i int) {
m.Store(i, i)
}(i)
}
for i := 0; i < 100; i++ {
go func(i int) {
v, ok := m.Load(i)
fmt.Printf("Load: %v, %v\n", v, ok)
}(i)
}
time.Sleep(1 * time.Second)
}