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