lazy val lock problem

76 views
Skip to first unread message

Andrzej Plutecki

unread,
Apr 19, 2017, 11:59:27 AM4/19/17
to dotty-internals
I wrote a comment on SIP-20. And I think problem is also with dotty because it is base on same concept.

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
}
}

Dmitry Petrashko

unread,
Apr 19, 2017, 12:08:40 PM4/19/17
to dotty-internals
Hi Andrzej,

Thanks for writing. You are right that the implementation has a formal bug. Strange that we haven't seen it ever occur in hours and hours of benchmarking the implementation both done by me and Alex.

Unfortunately your fix is both inefficient and incorrect:
 - inefficient in making CAS inside the first synchchronized block, it's a very pessimistic act that is rarely needed
 - incorrect in that the second synchronized block still has the same issue and can lead to a thread waiting forever.

Could you please come to https://github.com/lampepfl/dotty/pull/2276 and discuss proposed fix?

Thank you,
Dmitry
Reply all
Reply to author
Forward
0 new messages