I found a problem with implementation of lazy val. When one thread will initialize lazy val
and other check that val is already initializing then call
wait4Notification and set flag to 2. Then it is possibility that first
thread finished initializing and checked that flag which is set to 2 and
do notifyAll on monitor. After that second thread will call wait and it
will lock forever. Problem is with time between setting flag and wait
on monitor.
My solution is :
@inline def wait4Notification(t: Object, offset: Long, cur: Long, ord: Int) = {
println(s"${Thread.currentThread().getId()}-wait4Notification($t, $offset, $cur, $ord)")
var retry = true
while (retry) {
val cur = get(t, offset)
val state = STATE(cur, ord)
if (state == 1) {
val monitor = getMonitor(t, ord)
//make sure that thread will wait on monitor
monitor.synchronized {
if(CAS(t, offset, cur, 2, ord))
monitor.wait()
}
}
else if (state == 2) {
val monitor = getMonitor(t, ord)
monitor.synchronized {
monitor.wait()
}
}
else retry = false
}
}