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

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

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

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

01 、介紹

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

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

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

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

在需要并發(fā)讀寫操作 map 時,可以結合 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)
}

輸出結果:

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 結構體中的字段 flags,該字段用于標記 map 是否為寫入狀態(tài)。

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

03 、總結

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

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

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

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

相關文章

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

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

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

    GoLang bytes.Buffer基礎使用方法詳解

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

    Golang中 import cycle not allowed 問題

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

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

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

    一文詳解Golang中字符串的常見錯誤

    這篇文章主要來和大家深入討論一下Golang?中的字符串,并查看一些不同的場景,以避免常見錯誤,對大家掌握golang有一定的幫助,需要的可以了解下
    2023-10-10
  • 淺析GO語言的垃圾回收機制

    淺析GO語言的垃圾回收機制

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

    Golang中的錯誤處理的示例詳解

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

    go簡介及國內(nèi)鏡像源配置全過程

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

    一文帶你掌握Golang的反射基礎

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

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

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

最新評論