go version go1.22.1 windows/amd64
Windows 11 + amd64
x86_64 x86_64 GNU/Linux
---
序章
多個 給 map 寫入資料。
1、基本的map:make(map[any]any)
失敗。
2、sync.Map
成功。
測試場景:
1K 個 goroutines 給同一個 map 各自寫入 1W 資料,總1KW資料。
測試#1:普通map
程式碼:ben釋出於部落格園
// 多個 goroutines 寫入 多個資料
// 百萬+
// 失敗
func testMap2() {
map0 := make(map[any]any)
fmt.Println("len#1: ", len(map0))
const num1 = 1_000
const num2 = 10_000
for i := range [num1]int{} {
go func() {
for j := range [num2]int{} {
key := fmt.Sprintf("k%d#%d", i, j)
map0[key] = j // fatal error: concurrent map writes
}
fmt.Println("go end i=", i)
}()
}
fmt.Println("len#2: ", len(map0))
time.Sleep(5 * time.Second)
fmt.Println("len#3: ", len(map0)) // 等於 num1 * num2 ?
fmt.Println("end.")
}
測試結果:
執行失敗,出現了“fatal error: concurrent map writes”錯誤。
測試#2:sync.Map
// 多個 goroutines 寫入資料
// 每個寫入多個
func testMapForRoutines() {
map0ptr := new(sync.Map)
prtln("len of map #1: ", LenOfSyncMap(map0ptr))
const num1 = 1_000
const num2 = 10_000
for i := range [num1]int{} {
go func() {
for j := range [num2]int{} {
key := fmt.Sprintf("r#%d#%d", i, j)
map0ptr.Store(key, j)
}
prtln("end#i", i)
}()
}
prtln("len of map #2: ", LenOfSyncMap(map0ptr))
// sleepSeconds(10) // 資料 1KW 時,時間不夠
sleepSeconds(30)
prtln("len of map #3: ", LenOfSyncMap(map0ptr))
// OutputSyncMap(map0ptr)
sleepSeconds(5)
prtln("end.")
}
測試結果:ben釋出於部落格園
len of map #1: 0 ... len of map #3: 10000000 |
用到的函式:計算長度
// 計算 sync.Map 長度
func LenOfSyncMap(map0 *sync.Map) (len int64) {
map0.Range(func(key, value any) bool {
len++
return true
})
return
}
注意,這裡的返回值 有名稱——len,因此,return 後面沒有內容。
ben釋出於部落格園
type sync.Map 簡介
https://pkg.go.dev/sync@go1.22.3#Map
具體請看 文件。
描述:
Map is like a Go map[any]any but is safe for concurrent use by multiple goroutines without additional locking or coordination. Loads, stores, and deletes run in amortized constant time. |
END.
ben釋出於部落格園
本文連結:
https://www.cnblogs.com/luo630/p/18190211
ben釋出於部落格園
參考資料
1、
ben釋出於部落格園
ben釋出於部落格園