成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go 語言為什么不支持并發(fā)讀寫 map?

開發(fā) 前端
本文介紹 Go 語言為什么不支持并發(fā)讀寫 map?,Go 官方的說法是在多數(shù)情況下 map 只存在并發(fā)讀操作,如果原生支持并發(fā)讀寫,即降低了并發(fā)讀操作的性能。

01 、介紹

在 Go 語言項目開發(fā)中,我們經(jīng)常會使用哈希表 map,它的時間復(fù)雜度是 O(1),Go 語言中的 map 使用開放尋址法避免哈希碰撞。

Go 語言中的 map 并非原子操作,不支持并發(fā)讀寫操作。

Go 官方認為 map 在大多數(shù)情況下是使用 map 進行并發(fā)讀操作,僅在少數(shù)情況下是使用 map 進行并發(fā)讀寫操作。

如果 Go 語言中的 map 原生支持并發(fā)讀寫操作,在操作時需要先獲取互斥鎖,反而會降低只有并發(fā)讀操作時的性能。

在需要并發(fā)讀寫操作 map 時,可以結(jié)合 sync 包中的互斥鎖一起使用。

02 、并發(fā)讀寫 map

Go 支持并發(fā)讀 map,不支持并發(fā)讀寫 map。

示例代碼:

func main() {
 var m = make(map[int]string)

 go func() {
  for {
   m[1] = "xx"
  }
 }()

 go func() {
  for {
   _ = m[1]
  }
 }()
 time.Sleep(time.Second * 3)
}

輸出結(jié)果:

fatal error: concurrent map read and map write
// ...

閱讀上面這段代碼,我們并發(fā)讀寫 map 類型的變量 m,在運行時,返回致命錯誤 fatal error: concurrent map read and map write。

Go 語言中的 map 在運行時是怎么檢測到 map 的存在寫操作?

源碼:

const (
 // flags
 iterator     = 1 // there may be an iterator using buckets
 oldIterator  = 2 // there may be an iterator using oldbuckets
 hashWriting  = 4 // a goroutine is writing to the map
 sameSizeGrow = 8 // the current map growth is to a new map of the same size
)
// A header for a Go map.
type hmap struct {
 count     int // # live cells == size of map.  Must be first (used by len() builtin)
 flags     uint8
 B         uint8  // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
 noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
 hash0     uint32 // hash seed

 buckets    unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
 oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
 nevacuate  uintptr        // progress counter for evacuation (buckets less than this have been evacuated)

 extra *mapextra // optional fields
}

// Like mapaccess, but allocates a slot for the key if it is not present in the map.
func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
 // ...

done:
 if h.flags&hashWriting == 0 {
  fatal("concurrent map writes")
 }
 h.flags &^= hashWriting
 if t.IndirectElem() {
  elem = *((*unsafe.Pointer)(elem))
 }
 return elem
}

閱讀上面這段源碼,我們可以發(fā)現(xiàn)在 hmap 結(jié)構(gòu)體中的字段 flags,該字段用于標(biāo)記 map 是否為寫入狀態(tài)。

在訪問 map 時,通過判斷 hmap.flags 和 hashWriting 的值,可知是否有其它 goroutine 訪問 map,如果有,則返回致命錯誤 fatal("concurrent map writes")。

03 、總結(jié)

本文介紹 Go 語言為什么不支持并發(fā)讀寫 map,Go 官方的說法是在多數(shù)情況下 map 只存在并發(fā)讀操作,如果原生支持并發(fā)讀寫,即降低了并發(fā)讀操作的性能。

通過閱讀源碼,我們了解到在運行時檢測是否存在其它 goroutine 對 map 的寫操作,如果存在,則返回致命錯誤。

讀者朋友們在使用 map 時,要特別注意是否存在對 map 的并發(fā)寫操作,如果存在,要結(jié)合 sync 包的互斥鎖一起使用。

責(zé)任編輯:武曉燕 來源: Golang語言開發(fā)棧
相關(guān)推薦

2024-01-05 08:45:35

Go語言map

2021-10-27 07:15:36

Go 循環(huán)引用

2022-01-10 23:54:56

GoMap并發(fā)

2021-12-09 10:51:47

Go繼承

2021-12-15 07:49:22

Go語言設(shè)計

2023-01-28 08:05:32

轉(zhuǎn)換Go泛型

2024-03-12 09:13:28

Go語言main

2024-05-28 08:55:52

2021-11-08 11:02:01

Go函數(shù)重載

2023-02-26 23:36:08

PHPGo函數(shù)

2024-03-08 08:51:59

Gomain函數(shù)

2020-07-22 08:01:41

Python開發(fā)運算符

2020-10-09 06:48:19

Pythonswitch語句

2021-02-01 13:53:53

StringlongJava

2009-03-12 08:42:38

AndroidWMMTK

2021-06-11 00:03:31

鴻蒙智能手機

2021-08-02 09:31:20

Python工具代碼

2021-07-13 08:09:34

微博推特評論

2025-06-26 02:22:00

GoProtobuf標(biāo)簽

2023-04-03 11:21:29

PythonGoRust
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 精品九九| 国产精品成人一区二区 | 国产在线色 | 中文字幕免费中文 | 一级a性色生活片久久毛片 一级特黄a大片 | 在线欧美亚洲 | 久久久久久国产一区二区三区 | 精品国产欧美 | 在线亚洲电影 | 天天干狠狠操 | 亚洲欧美精品国产一级在线 | 久久久久国产精品午夜一区 | 成人精品一区二区三区四区 | 五月天国产 | 国产精品无码专区在线观看 | 欧美国产视频 | 在线国产一区二区三区 | 国精产品一区一区三区免费完 | 你懂的在线视频播放 | 自拍偷拍亚洲视频 | 黄色小视频入口 | 成年网站在线观看 | 在线看91| 日韩在线精品强乱中文字幕 | 精品网| 精品久久网 | 亚洲视频一区在线 | 久久久久久久久久久久亚洲 | 亚洲午夜视频 | 国产乱码精品一区二区三区忘忧草 | 久久综合久久综合久久 | 涩爱av一区二区三区 | 淫片专区| 亚洲精品视频播放 | 欧美在线视频一区二区 | 精品一区二区三区四区五区 | 天天操天天射综合网 | aa级毛片毛片免费观看久 | 亚洲第一网站 | 国产精品不卡一区 | 亭亭五月激情 |