掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
Go語言中的 map 在并發(fā)情況下,只讀是線程安全的,同時讀寫是線程不安全的。

下面來看下并發(fā)情況下讀寫 map 時會出現(xiàn)的問題,代碼如下:
// 創(chuàng)建一個int到int的映射
m := make(map[int]int)
// 開啟一段并發(fā)代碼
go func() {
// 不停地對map進行寫入
for {
m[1] = 1
}
}()
// 開啟一段并發(fā)代碼
go func() {
// 不停地對map進行讀取
for {
_ = m[1]
}
}()
// 無限循環(huán), 讓并發(fā)程序在后臺執(zhí)行
for {
}
運行代碼會報錯,輸出如下:
fatal error: concurrent map read and map write
錯誤信息顯示,并發(fā)的 map 讀和 map 寫,也就是說使用了兩個并發(fā)函數(shù)不斷地對 map 進行讀和寫而發(fā)生了競態(tài)問題,map 內(nèi)部會對這種并發(fā)操作進行檢查并提前發(fā)現(xiàn)。
需要并發(fā)讀寫時,一般的做法是加鎖,但這樣性能并不高,Go語言在 1.9 版本中提供了一種效率較高的并發(fā)安全的 sync.Map,sync.Map 和 map 不同,不是以語言原生形態(tài)提供,而是在 sync 包下的特殊結(jié)構(gòu)。
sync.Map 有以下特性:
并發(fā)安全的 sync.Map 演示代碼如下:
package main
import (
"fmt"
"sync"
)
func main() {
var scene sync.Map
// 將鍵值對保存到sync.Map
scene.Store("greece", 97)
scene.Store("london", 100)
scene.Store("egypt", 200)
// 從sync.Map中根據(jù)鍵取值
fmt.Println(scene.Load("london"))
// 根據(jù)鍵刪除對應(yīng)的鍵值對
scene.Delete("london")
// 遍歷所有sync.Map中的鍵值對
scene.Range(func(k, v interface{}) bool {
fmt.Println("iterate:", k, v)
return true
})
}
代碼輸出如下:
100 true
iterate: egypt 200
iterate: greece 97
代碼說明如下:
sync.Map 沒有提供獲取 map 數(shù)量的方法,替代方法是在獲取 sync.Map 時遍歷自行計算數(shù)量,sync.Map 為了保證并發(fā)安全有一些性能損失,因此在非并發(fā)情況下,使用 map 相比使用 sync.Map 會有更好的性能。

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流