question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

I wrote a comment on SIP-20. And I think problem is also with dotty because it is based 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 {
        println(s"${Thread.currentThread().getId} -$monitor - wait")
        monitor.wait()
      }
    }
    else retry = false
  }
}

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

2reactions
allanrenuccicommented, Nov 14, 2018

It seems I can reliably reproduce the issue with the following program:

object Test {
  var count = 0

  @volatile lazy val x: Int = {
    if (count < 100) {
      count += 1
      ???
    }
    1
  }

  def main(args: Array[String]): Unit = {
    def fetchLazy(): Unit = try x catch { case _: Throwable => fetchLazy() }

    for (_ <- 0 until 10) {
      new Thread(() => fetchLazy()).start()
    }
  }
}
2reactions
smartercommented, Jul 5, 2018

I think I just hit this for the first time, I was running our test suite but it got stuck at the very first test in dotty.tools.dotc.FromTastyTests.runTestFromTasty, see https://gist.github.com/smarter/588b5dcb19f26f7069c1f2b393995a56 for the jstack output.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Locking becaue of a local lazy val? - Question - Scala Users
hi internet, i did this: object x { def doStuff(file:File) { lazy val x = foo(file) ... } } to my surprise, my...
Read more >
Guide to lazy val in Scala - Baeldung
The compiler introduces a monitor for every lazy val. Due to this, compiler locks the whole instance during initialization. When multiple ...
Read more >
Lazy vals initialization shouldn't lock on owner #4798 - GitHub
We were recently reminded that initialization of lazy vals locks on the object holding the lazy val. This makes using lazy vals in...
Read more >
Scala's "lazy val" is using the double-checked locking pattern ...
And given that "Thing" in this sample is meant to be accessed by multiple threads, then if that access isn't synchronized, then the...
Read more >
[Scala] “Lazy” val in Scala. Overview | by mj park - Medium
During an evaluation of a lazy val, the whole instance is locked, which means when different lazy vals are accessed from multiple threads,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found