php小編香蕉帶來了一篇精彩的文章,講述了golang中切片的并發映射。在這篇文章中,我們將了解如何在并發環境中使用切片進行映射操作,并解釋了為什么切片在并發編程中非常有用。通過使用golang的并發機制,我們可以在多個goroutine中同時訪問和修改切片,從而提高程序的性能和效率。無論你是初學者還是有經驗的golang開發者,這篇文章都將給你帶來有價值的知識和實踐技巧。讓我們一起來探索golang中帶有切片的并發映射吧!
問題內容
在該領域的一位開發人員幾個月前離開后,我一直在嘗試解決并發問題,但我找不到解決此問題的適當方法。
對于上下文,我們將客戶數據加載到如下結構中:
[ 鍵 ] -> { 值 }
[客戶特定哈希] -> {數據點/文件切片}
示例 – 格式確實很糟糕,抱歉:
[a60d849ad97bfb833e1096941] -> { { StartDate: '01-02-2022', EndDate: '28-02-2022', DataFrames: [1598,921578,12981,21749,192578...]}, { StartDate: '01-03-2022', EndDate: '28-03-2022', DataFrames: [1234,1567,6781,126978...]}, }
登錄后復制
以上是因為我們有 100,000 名客戶,并且每天晚上都會啟動一個流程,根據每個客戶的哈希值(或實際上是一個存儲桶)來整合數據。在處理數據幀之前,我們會遍歷切片并將數據幀“合并”成一個大的數據幀,其中包含許多法律/會計規則。
它在 goroutine 中運行,以盡快索引所有數據點。
所以實現本質上是一個 sync.Map[string, []DataFrame]
但我注意到雖然映射操作受到保護,但附加到數據幀切片卻不受保護。每個哈希值每晚在該切片中可能有大約 20-30 個文件引用。
在過去的兩年里,客戶數據很有可能被錯誤地合并,我的任務是修復它。在sync.map之前,他們再次使用了帶有Map的RWMutex,但不是切片,它指向本文作為指南。
首先,包含切片的 Map 的想法是適當的數據結構嗎?
我嘗試創建一個基于 RWMutex 的切片處理程序,但想知道 Map 是否可以有一個 chan DataFrame
來代替在索引客戶文件時放入,然后一旦完成,第二步將其合并到一個數組中(如len(chanx)
) 會被知道嗎?
我主要來自 Java,所以我可能對一些術語感到困惑,所以我很抱歉。
解決方法
您有兩個不同的問題:
-
更新地圖時出現并發問題
更新地圖條目時出現并發問題
sync.Map
將防止 1,但不能防止 2。
解決這個問題的一種方法是:
sync.Map[string, *DFrame]
登錄后復制
哪里
type DFrame struct { sync.RWMutex Data []DataFrame }
登錄后復制
一旦從地圖中獲取條目,您應該 Lock
或 RLock
它,然后使用數據。這不僅僅限于切片的附加。即使您只從數據幀中讀取,您也必須 RLock
該結構。
因此,如果您要附加新的數據框:
df := &DFrame{} entry,_:=m.LoadOrStore(key, df) dfEntry:=entry.(*DFrame) dfEntry.Lock() dfEntry.Data=append(dfEntry.Data, newDataFrame) dfEntry.Unlock()
登錄后復制