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

Go 語言為什么不支持并發讀寫 map?

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

01 、介紹

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

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

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

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

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

02 、并發讀寫 map

Go 支持并發讀 map,不支持并發讀寫 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)
}

輸出結果:

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

閱讀上面這段代碼,我們并發讀寫 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
}

閱讀上面這段源碼,我們可以發現在 hmap 結構體中的字段 flags,該字段用于標記 map 是否為寫入狀態。

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

03 、總結

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

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

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

責任編輯:武曉燕 來源: Golang語言開發棧
相關推薦

2024-01-05 08:45:35

Go語言map

2021-10-27 07:15:36

Go 循環引用

2022-01-10 23:54:56

GoMap并發

2021-12-09 10:51:47

Go繼承

2021-12-15 07:49:22

Go語言設計

2023-01-28 08:05:32

轉換Go泛型

2024-03-12 09:13:28

Go語言main

2024-05-28 08:55:52

2021-11-08 11:02:01

Go函數重載

2023-02-26 23:36:08

PHPGo函數

2020-07-22 08:01:41

Python開發運算符

2020-10-09 06:48:19

Pythonswitch語句

2024-03-08 08:51:59

Gomain函數

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工具代碼

2025-06-26 02:22:00

GoProtobuf標簽

2023-04-03 11:21:29

PythonGoRust

2021-07-13 08:09:34

微博推特評論
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一级黄色片在线看 | 日韩免费一区二区 | 日本一本视频 | 久草网址 | 国产精品成人国产乱一区 | 精品久久九九 | 成人在线中文字幕 | 9久9久| 九九色综合 | 麻豆精品国产免费 | 精品91久久 | 日本视频在线播放 | 91精品久久久久久久久 | 精品1区 | 91精品久久久久久久99 | 色综合欧美 | 天天夜夜人人 | 久久精品国产99国产精品 | www.久久久久久久久久久久 | 欧美1级 | 国精日本亚洲欧州国产中文久久 | 爱操av| 亚洲日韩中文字幕一区 | 欧美激情一区二区三区 | 亚洲电影成人 | 欧美一级黄色免费看 | 成人精品国产免费网站 | 一级黄色片免费 | 美女久久久久久久久 | 欧美一级免费 | 亚洲综合一区二区三区 | 羞羞视频网站免费观看 | 日本三级黄视频 | 国产成人免费视频网站视频社区 | 五月婷婷激情 | 天堂成人av | 中文在线观看视频 | 国产人免费人成免费视频 | 成人小视频在线观看 | 国产精品特级毛片一区二区三区 | 国产精品久久久久久久久久久久午夜片 |