Consider the following DCL example written in Kotlin:
@Volatile
private var property: String? = null
private val lock = ReentrantLock()
fun singletonValue(): String {
if (property == null) {
lock.withLock {
if (property == null) {
property = "Hello World"
}
}
}
return property!!
}
It's pretty much the same as its Java counterpart discussed like two decades ago, when Java Memory Model was corrected with the transition from Java 1.4 to Java 5. Having said that, I'm perfectly sure the above code fragment will behave correctly when run on the JVM.
Now, let's use a lateinit var instead:
@Volatile
private lateinit var property: String
private val lock = ReentrantLock()
fun singletonValue(): String {
if (!::property.isInitialized) {
lock.withLock {
if (!::property.isInitialized) {
property = "Hello World"
}
}
}
return property
}
Is it semantically equivalent to the original example? Does it maintain the same atomicity and visibility guarantees?