Tommy

Tommy

写代码是热爱,但也是生活 !
github

Why is Go map not thread-safe?

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)
}
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.