I have a piece of code from this website which has double checked locking for initialization of an object.
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()
}
}
This piece of code has mutex.RLock()
before first nil check.
Why is that required? (it is explained in the page but I couldn't understand) And doesn't it add overhead becuase everytime checkSyncProducer is called read lock will be taken and released.
Should there be one more nil check before acquiring read lock like:
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()
}
}
}
First nil check will ensure that RLock is not taken unnecessarily. Am I correct?