別把輸入輸出放進(jìn)鎖里)
合并沖突時(shí)別把輸入輸出放進(jìn)鎖里合并沖突最危險(xiǎn)的地方不一定是編譯錯(cuò)誤而是兩個(gè)局部正確的改動(dòng)被拼在一起后改變了并發(fā)邊界。例如遠(yuǎn)程調(diào)用、數(shù)據(jù)庫(kù)查詢或大循環(huán)落在Lock和Unlock之間會(huì)讓鎖持有時(shí)間取決于外部系統(tǒng)其他請(qǐng)求只能排隊(duì)等待。評(píng)審這類改動(dòng)時(shí)先明確共享狀態(tài)是什么再把讀取、遠(yuǎn)程請(qǐng)求和計(jì)算放在鎖外。必要時(shí)先在鎖內(nèi)復(fù)制當(dāng)前狀態(tài)解鎖后執(zhí)行慢操作最后在短臨界區(qū)內(nèi)按版本號(hào)或條件提交結(jié)果。不要為了避免鎖競(jìng)爭(zhēng)直接改成無(wú)鎖實(shí)現(xiàn)除非能證明內(nèi)存安全和一致性。mu.RLock() snapshot : state.clone() mu.RUnlock() result, err : fetch(ctx, snapshot.Key) // I/O 在鎖外 if err ! nil { return err } mu.Lock() if state.Version snapshot.Version { state.Result result } mu.Unlock()慢鎖告警可以幫助定位問(wèn)題但閾值要依據(jù)服務(wù)目標(biāo)設(shè)置而且記錄堆棧會(huì)產(chǎn)生開銷宜按采樣或在診斷開關(guān)下啟用。sync.RWMutex的使用也應(yīng)以 profile 為依據(jù)讀鎖多不代表一定優(yōu)于普通互斥鎖。提交前至少運(yùn)行受影響包的單測(cè)和競(jìng)態(tài)檢測(cè)若改動(dòng)涉及熱點(diǎn)路徑再比較同一負(fù)載下的 benchmark、block profile 與 mutex profile。性能數(shù)字必須標(biāo)注環(huán)境、并發(fā)與數(shù)據(jù)集不能脫離條件作為結(jié)論。