我有一段代碼,它對對象的初始化進行了雙重檢查鎖定。func checkSyncProducer() {? ? mutex.RLock()? ? if syncProducer == nil {? ? ? ? mutex.RUnlock()? ? ? ? mutex.Lock()? ? ? ? defer mutex.Unlock()? ? ? ? if syncProducer == nil {? ? ? ? ? ? syncProducer? = createSyncKafkaProducer() //this func will initialize syncProducer.? ? ? ? }? ? } else {? ? ? ? defer mutex.RUnlock()? ? }}這段代碼在mutex.RLock()第一次 nil 檢查之前。為什么需要這樣?(它在頁面中有解釋,但我無法理解)并且它不會增加開銷,因為每次調用 checkSyncProducer 時都會獲取和釋放讀取鎖。在獲取讀鎖之前是否應該再進行一次 nil 檢查,例如:func checkSyncProducer() {? ? if syncProducer == nil {? ? ? ? mutex.RLock()? ? ? ? if syncProducer == nil {? ? ? ? ? ? mutex.RUnlock()? ? ? ? ? ? mutex.Lock()? ? ? ? ? ? defer mutex.Unlock()? ? ? ? ? ? if syncProducer == nil {? ? ? ? ? ? ? ? createSyncKafkaProducer()? ? ? ? ? ? }? ? ? ? } else {? ? ? ? ? ? defer mutex.RUnlock()? ? ? ? }? ? }}第一個 nil 檢查將確保 RLock 不會被不必要地占用。我對么?
2 回答

慕標5832272
TA貢獻1966條經驗 獲得超4個贊
如果你沒有獲取 RLock 來讀取syncProducer,那就是數據競爭,因為另一個 goroutine 可能會更新它。
如果你假設對指針變量的讀/寫是原子的,這看起來是無害的——活潑的讀syncProducer永遠不會導致不正確的行為。如果你不做這個原子假設,如果你不走運的話,讀取可能只產生指針的一些字節,你的程序就會崩潰。
根據您使用的體系結構、機器字長、編譯器版本等,這可能會也可能不會。但這RLock避免了任何擔憂。
與其顯式地亂用 RWLocks,不如使用它(假設目標是懶惰地初始化一個變量):
var (
syncOnce sync.Once
syncProducerInternal *syncProducerType
)
func syncProducer() *syncProducerType {
syncOnce.Do(func() { syncProducerInternal = createSyncKafkaProducer() })
return syncProducerInternal
}
然后需要同步生產者的代碼可以調用該syncProducer()函數來獲取它,而永遠不會看到 nil 指針。
- 2 回答
- 0 關注
- 184 瀏覽
添加回答
舉報
0/150
提交
取消