Skip to content

Deadlock with inner object class init #9312

@scabug

Description

@scabug

When the following program is run, the threads end up in a deadlock.

object DeadLockTest {
  def main(args: Array[String]): Unit = {
    def run(block: => Unit): Unit =
      new Thread(new Runnable {def run(): Unit = block}).start()

    run {println(Parent.Child1)}
    run {println(Parent.Child2)}

  }

  object Parent { self =>
    trait Child {
      Thread.sleep(2000) // ensure concurrent behavior
      val parent = self
      def siblings = parent.children - this
    }

    object Child1 extends Child
    object Child2 extends Child

    final val children = Set(Child1, Child2)
  }
}

The deadlock happens because the Child classes are initialized before the Parent. This leads to the following chain of actions:

  • thread 1 starts to init class Child1 (calls the static initializer cinit, which calls the constructor init)
  • thread 2 starts to init class Child2
  • thread 1 starts to init Parent to get a reference to it into the val parent
  • thread 2 tries to get reference to Parent to place it in the val parent, but as the class Parent is being inited by thread 1, it waits
  • thread 1 tries to get reference to Child2 to place it into the val children, but as the Child2 class is being initied by thread2, it waits

For me as a programmer, when looking at the syntax, I would expect Parent.Child1 to mean that we take a reference to Parent, which has a field called Child1 containing the reference to the singleton object Child1. This would ensure that Parent1 is initialized before Child2 can be used. Ofcourse what really happens is that a reference to Parent.Child1 just uses the Parent1.MODULE$ to get the reference without bother Parent at all. Thus to me this is a bug/design failure in how scala handles inner objects.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions