欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語(yǔ)言map不支持并發(fā)寫操作的原因

 更新時(shí)間:2024年01月01日 11:12:34   作者:frank  
Go語(yǔ)言為什么不支持并發(fā)讀寫map?,Go官方的說(shuō)法是在多數(shù)情況下map只存在并發(fā)讀操作,如果原生支持并發(fā)讀寫,即降低了并發(fā)讀操作的性能,在使用?map?時(shí),要特別注意是否存在對(duì)?map?的并發(fā)寫操作,如果存在,要結(jié)合?sync?包的互斥鎖一起使用,

本文介紹 Go 語(yǔ)言為什么不支持并發(fā)讀寫 map?,Go 官方的說(shuō)法是在多數(shù)情況下 map 只存在并發(fā)讀操作,如果原生支持并發(fā)讀寫,即降低了并發(fā)讀操作的性能。在使用 map 時(shí),要特別注意是否存在對(duì) map 的并發(fā)寫操作,如果存在,要結(jié)合 sync 包的互斥鎖一起使用。

01 、介紹

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

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

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

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

在需要并發(fā)讀寫操作 map 時(shí),可以結(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,在運(yùn)行時(shí),返回致命錯(cuò)誤 fatal error: concurrent map read and map write。

Go 語(yǔ)言中的 map 在運(yùn)行時(shí)是怎么檢測(cè)到 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)。

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

03 、總結(jié)

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

通過(guò)閱讀源碼,我們了解到在運(yùn)行時(shí)檢測(cè)是否存在其它 goroutine 對(duì) map 的寫操作,如果存在,則返回致命錯(cuò)誤。

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

到此這篇關(guān)于Go語(yǔ)言map不支持并發(fā)寫操作的原因的文章就介紹到這了,更多相關(guān)Go中map不支持并發(fā)寫內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言中http和mysql的實(shí)現(xiàn)代碼

    Go語(yǔ)言中http和mysql的實(shí)現(xiàn)代碼

    本文通過(guò)實(shí)例代碼給大家介紹了Go語(yǔ)言中http和mysql的實(shí)現(xiàn)代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-11-11
  • GoLang bytes.Buffer基礎(chǔ)使用方法詳解

    GoLang bytes.Buffer基礎(chǔ)使用方法詳解

    Go標(biāo)準(zhǔn)庫(kù)中的bytes.Buffer(下文用Buffer表示)類似于一個(gè)FIFO的隊(duì)列,它是一個(gè)流式字節(jié)緩沖區(qū),我們可以持續(xù)向Buffer尾部寫入數(shù)據(jù),從Buffer頭部讀取數(shù)據(jù)。當(dāng)Buffer內(nèi)部空間不足以滿足寫入數(shù)據(jù)的大小時(shí),會(huì)自動(dòng)擴(kuò)容
    2023-03-03
  • Golang中 import cycle not allowed 問(wèn)題的解決方法

    Golang中 import cycle not allowed 問(wèn)題

    這篇文章主要介紹了Golang中 import cycle not allowed 問(wèn)題的解決方法,問(wèn)題從描述到解決都非常詳細(xì),需要的小伙伴可以參考一下
    2022-03-03
  • Go基礎(chǔ)系列:Go切片(分片)slice詳解

    Go基礎(chǔ)系列:Go切片(分片)slice詳解

    這篇文章主要介紹了Go語(yǔ)言中的切片(分片)slice詳細(xì)說(shuō)明?,需要的朋友可以參考下
    2022-04-04
  • 一文詳解Golang中字符串的常見(jiàn)錯(cuò)誤

    一文詳解Golang中字符串的常見(jiàn)錯(cuò)誤

    這篇文章主要來(lái)和大家深入討論一下Golang?中的字符串,并查看一些不同的場(chǎng)景,以避免常見(jiàn)錯(cuò)誤,對(duì)大家掌握golang有一定的幫助,需要的可以了解下
    2023-10-10
  • 淺析GO語(yǔ)言的垃圾回收機(jī)制

    淺析GO語(yǔ)言的垃圾回收機(jī)制

    今天我們來(lái)聊聊golang是如何進(jìn)行垃圾回收的,我們知道,目前各語(yǔ)言進(jìn)行垃圾回收的方法有很多,如引用計(jì)數(shù)、標(biāo)記清除、分代回收、三色標(biāo)記等,各種方式都有其特點(diǎn),文中介紹的非常詳細(xì),感興趣的小伙伴跟著小編一起學(xué)習(xí)吧
    2023-07-07
  • Golang中的錯(cuò)誤處理的示例詳解

    Golang中的錯(cuò)誤處理的示例詳解

    這篇文章主要為大家詳細(xì)介紹了Golang中的錯(cuò)誤處理的相關(guān)資料,文章中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Golang有一定幫助,需要的可以參考一下
    2022-12-12
  • go簡(jiǎn)介及國(guó)內(nèi)鏡像源配置全過(guò)程

    go簡(jiǎn)介及國(guó)內(nèi)鏡像源配置全過(guò)程

    本文介紹了Go語(yǔ)言的基本概念和環(huán)境配置,包括GOROOT、GOPATH和GOMODULE的設(shè)置,還展示了如何在IDEA中配置Go語(yǔ)言的開(kāi)發(fā)環(huán)境,并通過(guò)一個(gè)簡(jiǎn)單的“HelloWorld”項(xiàng)目來(lái)熟悉Go語(yǔ)言的基本語(yǔ)法和開(kāi)發(fā)流程
    2025-01-01
  • 一文帶你掌握Golang的反射基礎(chǔ)

    一文帶你掌握Golang的反射基礎(chǔ)

    go的反射是由其標(biāo)準(zhǔn)庫(kù)中的reflect包實(shí)現(xiàn),該reflect包實(shí)現(xiàn)了在運(yùn)行時(shí)進(jìn)行反射的能力,本篇主要介紹了reflect的常用的幾個(gè)方法,希望對(duì)大家有所幫助
    2023-02-02
  • 使用golang生成prometheus格式數(shù)據(jù)

    使用golang生成prometheus格式數(shù)據(jù)

    Prometheus是一個(gè)開(kāi)源的監(jiān)控系統(tǒng),擁有許多Advanced?Feature,本文將介紹Primetheus?client的使用,并基于golang生成prometheus格式數(shù)據(jù),希望對(duì)大家有所幫助
    2025-02-02

最新評(píng)論