是因為多個goroutine對同一個map產出了競爭,解決這個問題的方法有兩個,一個是用sync.Map,另一個是加鎖。 sync.map是go1.9新加的特性,這裡暫且先不討論。而且目前業務場景用讀寫鎖定完全可以解決,所以決定使用讀寫鎖定。
讀寫鎖
RWMutex是一個讀寫鎖,該鎖可以加多個讀鎖或寫鎖,其常用於讀取次數遠遠多於寫次數的場景。 (推薦學習:go)
func (rw *RWMutex) Lock() 寫鎖,如果在添加寫鎖之前已經有其他的讀鎖和寫鎖,則lock就會阻塞直到該鎖可用,為確保該鎖最終可用,已阻塞的Lock 呼叫會從獲得的鎖中排除新的讀取器,即寫鎖權限高於讀鎖,有寫鎖時優先進行寫鎖定
func (rw *RWMutex) Unlock() 寫鎖定解鎖,如果沒有進行寫入鎖定,則會造成一個執行時間錯誤
func (rw *RWMutex) RLock () 讀鎖,當有寫鎖時,無法載入讀鎖,當只有讀鎖或沒有鎖時,可以載入讀鎖,讀鎖可以載入多個,所以適用於"讀多寫少"的場景
func (rw *RWMutex) RUnlock() 讀鎖解鎖,RUnlock 撤銷單次RLock 調用,它對於其它同時存在的讀取器則沒有效果。若rw 並沒有為讀取而鎖定,呼叫RUnlock 就會引發一個運行時錯誤
概括:
讀鎖不能阻塞讀鎖
讀鎖需要阻塞寫鎖,直到所有讀鎖都釋放
寫鎖需要阻塞讀鎖,直到所有寫鎖都釋放
寫鎖需要阻塞寫鎖
#上程式碼:
type MapWithLock struct { //把读写锁和资源map封装在一起 sync.RWMutex M map[string]Kline } var KlineDataMemory = make(map[string] interface{}) var InstrLock sync.RWMutex var counter = MapWithLock{ // 生成一个带有锁和map的实例,然后就可以使用啦 InstrLock, KlineDataMemory, } . . . counter.RLock() //加读锁 for _, v := range counter.M { instrID = v.InstrumentID break } counter.RUnlock() //解除读锁 加锁和解锁必须成对出现,并且建议放在同一层次的代码块中
以上是golang讀鎖有什麼用的詳細內容。更多資訊請關注PHP中文網其他相關文章!