Tommy

Tommy

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

Go map為什麼是非執行緒安全的?

map 預設是並發不安全的,同時對 map 進行並發讀寫時,程序會 panic,原因如下:

Go 官方在經過了長時間的討論後,認為 Go map 更應適配典型使用場景(不需要從多個 goroutine 中進行安全訪問),而不是為了小部分情況(並發訪問),導致大部分程序付出加鎖代價(性能),決定了不支持。

場景: 2 個協程同時讀和寫,以下程序會出現致命錯誤: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("map第%d個元素值是%d\n", i, s[i])
        }(i)
    }
    time.Sleep(1 * time.Second)
}

如果想實現 map 線程安全,有兩種方式:

方式一:使用讀寫鎖 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("map第%d個元素值是%d\n", i, s[i])
            lock.RUnlock()
        }(i)
    }
    time.Sleep(1 * time.Second)
}

方式二:使用 Go 提供的 sync.Map

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)
}
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。