Skip to content

Should method local modules lock on modules use the new finer grained locks of local lazy vals? #235

@retronym

Description

@retronym
Welcome to Scala 2.11.8
Type in expressions for evaluation. Or try :help.

scala> class C { def foo = { object O { assert(Thread.holdsLock(C.this)) }; O }}; new C().foo
defined class C
res0: AnyRef = C$O$2$@3ada9e37

scala> class C { def foo = { lazy val O = { assert(Thread.holdsLock(C.this)) }; O }}; new C().foo
defined class C

In 2.12 / scala/scala#5294, the latter changed:

the locking scope of a local lazy val is now tied to the lazy val, following Dotty's encoding

Welcome to Scala 2.12.0-...

scala> class C { def foo = { lazy val O = { assert(Thread.holdsLock(C.this)) }; O }}; new C().foo
java.lang.AssertionError: assertion failed

This change was motivated by a variation of the programs above, in which the lazy val was enclosed in a lambda. In 2.11, the enclosing this that we locked on during lazy val init was the anon function class. In 2.12, it became the source-level enclosing class of the lambda. This introduced a class of deadlocks to previously working code, so it seemed like the right time to moving to finer grained locks.

However, we have not made a corresponding change for method-local modules:

Welcome to Scala 2.12.0-...

scala> class C { def foo = { object O { assert(Thread.holdsLock(C.this)) }; O }}; new C().foo
defined class C
res0: AnyRef = C$O$2$@746b18fd

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions