golang_並發安全: slice和map並發不安全及解決方法


golang_並發安全: slice和map並發不安全及解決方法

Grayan · 2020-07-21 15:32:48 · 1771 次點擊 · 預計閱讀時間 1 分鍾 · 不到1分鍾之前 開始瀏覽    
這是一個創建於  2020-07-21 15:32:48 的文章,其中的信息可能已經有所發展或是發生改變。

並發安全

並發安全也叫線程安全,在並發中出現了數據的丟失,稱為並發不安全

map和slice都是並發不安全的

切片並發不安全

場景: 10000個協程同時添加切片

var s []int func appendValue(i int) { s = append(s, i) } func main() { for i := 0; i < 10000; i++ { //10000個協程同時添加切片 go appendValue(i) } for i, v := range s { //同時打印索引和值 fmt.Println(i, ":", v) } } 

Output:

slice並發不安全

沒有到9999,說明有數據丟失

解決方法: 加鎖

var s []int var lock sync.Mutex //互斥鎖 func appendValue(i int) { lock.Lock() //加鎖 s = append(s, i) lock.Unlock() //解鎖 } func main() { for i := 0; i < 10000; i++ { go appendValue(i) } //sort.Ints(s) //給切片排序,先排完序再打印,和下面一句效果相同 time.Sleep(time.Second) //間隔1s再打印,防止一邊插入數據一邊打印時數據亂序 for i, v := range s { fmt.Println(i, ":", v) } } 

總結: slice在並發執行中不會報錯,但是數據會丟失

map並發不安全

場景: 2個協程同時讀和寫

func main() { m := make(map[int]int) go func() { //開一個協程寫map for i := 0; i < 10000; i++ { m[i] = i } }() go func() { //開一個協程讀map for i := 0; i < 10000; i++ { fmt.Println(m[i]) } }() //time.Sleep(time.Second * 20) for { ; } } 

Output:

map並發不安全

解決方法:盡量不要做map的並發,如果用並發要加鎖,保證map的操作要么讀,要么寫。

var lock sync.Mutex func main() { m:=make(map[int]int) go func() { //開一個協程寫map for i:=0;i<10000 ;i++ { lock.Lock() //加鎖 m[i]=i lock.Unlock() //解鎖 } }() go func() { //開一個協程讀map for i:=0;i<10000 ;i++ { lock.Lock() //加鎖 fmt.Println(m[i]) lock.Unlock() //解鎖 } }() time.Sleep(time.Second*20) } 

總結: map在並發執行中會直接報錯


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM